显示列表取决于搜索结果的角度

时间:2018-05-26 11:44:50

标签: angular typescript components

我的基础是英雄导游之旅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>

我尝试将其移至app-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);
}

这里的问题是this.monsters $是Observable类型,我需要一种怪物才能订阅。或者还有其他/更简单的方法来实现这一目标吗?

怪物服务:

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 个答案:

答案 0 :(得分:2)

错误本身就是自解释的,只需更改“ getMonsters()”方法,如下所示: -

getMonsters(): void{
 this.monsters$ = this.monsterService.getMonsters();
}

答案 1 :(得分:0)

因此,如果你有一个可能在组件初始化时下载一次的怪物列表,那么你不需要为怪物提供Observable流,因为当你输入内容时这个列表不会改变。这里只有异步的东西是用户输入,为此你可以创建新的流:

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

然后更改ngFor循环以使用filtredMonsters $:

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

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

答案 2 :(得分:0)

如果您的MonsterService有方法searchMonsters,您也可以使用它来获取filtredMonsters $但是用switchMap替换map运算符:

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