代码之家  ›  专栏  ›  技术社区  ›  Audiosleef

根据搜索结果显示列表

  •  0
  • Audiosleef  · 技术社区  · 7 年前

    我是基于 Hero-Search 来自《英雄之旅》教程。在那里你可以搜索英雄,返回一个 list 这只会显示包含字母的结果,让你点击你想要的英雄。

    我想修改它,使我的当前 list 根据输入到搜索框中的内容进行过滤。

    这是你在照片上看到的:

    <h1><span id="monstersTitle">Monsters</span></h1>
    <app-monster-search></app-monster-search>
    <ul class="monsters">
     <li *ngFor="let monster of monsters">
      <span class="badge" (click)="addToEncounter(monster)">{{monster.name}} 
      </span> Hitpoints: {{monster.hitPoints}} Armor: {{monster.armor}}
     </li>
    </ul>
    

    我尝试将其移动到应用程序monster search组件:

    <div id="search-component">
    <h4>Monster Search</h4>
    
    <input #searchBox id="search-box" (keyup)="search(searchBox.value)" />
    <ul class="monsters">
     <li *ngFor="let monster of monsters$ | async">">
      <span class="badge" (click)="addToEncounter(monster)">{{monster.name}} 
       </span> Hitpoints: {{monster.hitPoints}} Armor: {{monster.armor}}
     </li>
    </ul>
    
    export class MonsterSearchComponent implements OnInit {
    monsters$: Observable<Monster[]>;
    private searchTerms = new Subject<string>();
    
    constructor(private monsterService: MonsterService, private sharedService: 
    SharedMonsterService) {}
    
    // Push a search term into the observable stream.
    search(term: string): void {
     this.searchTerms.next(term);
    }
    
    getMonsters(): void{
     this.monsterService.getMonsters()
      .subscribe(monster => this.monsters$ = monster); //error on "this.monsters$" = Type 'Monster[]' is not assignable to type 'Observable<Monster[]>
    }
    
    addToEncounter(monster){
     this.sharedService.publishMonster(monster);
    }
    

    这里的问题是这个。monsters$是可观察的类型,我需要一种可以订阅的怪物类型。还是有其他更简单的方法来实现这一点?

    怪物服务:

    public getMonsters(): Observable<Monster[]>{
    return this.http.get<Monster[]>(this.monsterUrl).pipe(
      tap(heroes => this.log(`fetched heroes`)),
      catchError(this.handleError('getHeroes', []))
    );
    }
    
    searchMonsters(term: string): Observable<Monster[]> {
    if (!term.trim()) {
      // if not search term, return empty hero array.
      return of([]);
    }
    return this.http.get<Monster[]>(`${this.monsterUrl}/?name=${term}`).pipe(
      tap(_ => this.log(`found monsters matching "${term}"`)),
      catchError(this.handleError<Monster[]>('searchMonsters', []))
    );
    

    }

    编辑:

    作为将来的参考,如果其他人正在寻找类似的东西:

    <div id="search-component">
    <h4>Monster Search</h4>
    
    <input #searchBox id="search-box" (keyup)="search(searchBox.value)"/>
    <ul class="monsters">
    <li *ngFor="let monster of (monsters$ | async)">
      <span class="badge" (click)="addToEncounter(monster)">{{monster.name}} 
     </span> Hitpoints: {{monster.hitPoints}}
      Armor: {{monster.armor}}
     </li>
     </ul>
     </div>
    <div *ngIf="!searchBox.value">
     <ul class="monsters">
     <li *ngFor="let monster of (monsters)">
      <span class="badge" (click)="addToEncounter(monster)">{{monster.name}} 
      </span> Hitpoints: {{monster.hitPoints}}
      Armor: {{monster.armor}}
     </li>
     </ul>
    </div>
    
    3 回复  |  直到 7 年前
        1
  •  2
  •   Yatharth Varshney    7 年前

    错误本身是不言自明的,只要改变就行了。” getMonsters() “方法如下所示:-

    getMonsters(): void{
     this.monsters$ = this.monsterService.getMonsters();
    }
    
        2
  •  0
  •   pascal    7 年前

    所以,如果你有一个怪物列表,可能在组件初始化时下载一次,你不需要观察怪物流,因为当你输入一些东西时,这个列表不会改变。这里唯一的异步功能是用户输入,为此您可以创建新的流:

    this.filtredMonsters$ = this.searchTerms.pipe(
      map(searchTerms => this.monsters.filter(monster => monster.name.startsWith(searchTerms)))
    

    然后将ngFor循环更改为使用FilterdMonsters$:

    <li *ngFor="let monster of filtredMonsters$ | async">
    

    但请记住,只有当怪物列表可用时,才能创建该流。

        3
  •  0
  •   pascal    7 年前

    如果你的Monsters服务有方法searchMonsters,你也可以用它来获得FilterdMonsters$,但用switchMap替换map operator:

    this.filtredMonsters$ = this.searchTerms.pipe(
      switchMap(searchTerms => this.monsterService.searchMonsters(searchTerms)));