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