在父组件中,我有一个Tour [] tours_filtered: Observable<Tour[]>
流,我在http请求的subscribe函数中分配
this.api.getTours().subscribe(
result => {
this.tours_filtered = of(result.tours);
}
)
在视图中,我使用异步管道显示流
<app-tour-box [tour]="tour" *ngFor="let tour of tours_filtered | async"></app-tour-box>
到目前为止所有工作都按预期进行。在子组件中,我有一个输入文本,它发出用户插入的值,以过滤Tour by title的数组。
在父组件中我监听函数中发出的值,我切换到使用switchMap过滤了该值的Tour []的新流
onSearchTitle(term: string) {
this.tours_filtered.pipe(
switchMap(
(tours) => of( tours.filter((tour) => tour.name.toLowerCase().includes(term)) )
)
)
}
我认为异步管道一直在监听以反映应用它的数组的变化,所以我认为我不必在上面的函数中订阅,但是当我输入输入时,视图中没有任何变化过滤结果。
如果我将新流分配给subscribe函数中的原始数组,则结果会正确更新
onSearchTitle(term: string) { this.tours_filtered.pipe( switchMap((tours) => of(tours.filter((tour) => tour.name.toLowerCase().includes(term)))) ).subscribe( val => { this.tours_filtered = of(val); }) }
这个程序是否正确?我可以避免订阅因为我已经使用了异步管道吗?有更好的方法来实现我的目标吗?
编辑:
也许我找到了一个解决方案,我必须像这样为变量分配一个新流
onSearchTitle(term: string) {
this.tours_filtered = of(this.city.tours).pipe(
switchMap((tours) => of(tours.filter((tour) => tour.name.toLowerCase().includes(term))))
);
}
我不需要再次订阅,视图中的结果会根据用户键入的搜索词进行更改。这是正确的方法吗?
我认为在您的情况下,解决方案应该如下工作:
onSearchTitle(term: string) {
this._searchTerm = term;
this.tours_filtered = of(
this.city.tours.filter((tour) => tour.name.toLowerCase().includes(term))
)
}
因为在您的示例中,您不会更改ngFor
中使用的observable。因此它不起作用。
但是,我没有看到在这里使用observable的原因,除非这是第一步,你将来要从服务器获取这些数据
UPDATE
对您而言,最佳解决方案是将您的输入视为可观察的并观察更改:
// your.component.ts
export class AppComponent {
searchTerm$ = new BehaviorSubject<string>('');
results = this.search(this.searchTerm$);
search(terms: Observable<string>) {
return terms
.pipe(
debounceTime(400),
distinctUntilChanged(),
switchMap(term => {
return of(this.city.tours.filter((tour) => tour.name.toLowerCase().includes(term)))
}
)
)
}
}
// your.template.html
...
<input type="" (input)="searchTerm$.next($event.target.value)">
...
此外,添加debounceTime
和distinctUntilChanged
以获得更好的用户体验和更少的搜索请求将会很棒。
有关详细信息,请参阅full example。另外,请参阅this article以获得更详细的解释