在父组件中,我有一个Tour [] tours_filtered: Observable<Tour[]>
流,该流是在http请求的订阅功能中分配的
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数组。
在父组件中,我侦听一个函数中发出的值,然后切换到新的Tour []流(使用switchMap对该值进行过滤)
onSearchTitle(term: string) {
this.tours_filtered.pipe(
switchMap(
(tours) => of( tours.filter((tour) => tour.name.toLowerCase().includes(term)) )
)
)
}
我认为异步管道一直在监听以反映对其应用的数组的更改,因此我认为我不必订阅上面的函数,但是当我键入内容时视图中没有任何变化输入以过滤结果。
如果我将新流分配给订阅函数中的原始数组,结果将正确更新
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))))
);
}
,并且我不需要再次订阅,视图中的结果根据用户键入的搜索词而变化。这是正确的方法吗?
答案 0 :(得分:0)
我认为在您的情况下解决方案应按以下方式工作:
onSearchTitle(term: string) {
this._searchTerm = term;
this.tours_filtered = of(
this.city.tours.filter((tour) => tour.name.toLowerCase().includes(term))
)
}
因为在您的示例中,您没有更改ngFor
中使用的可观察值。因此它不起作用。
但是,除非这是第一步,否则我看不出在这里使用可观察对象的原因,并且您将来将要从服务器获取此数据
更新
最适合您的解决方案是将您的输入视为可观察到的并注意更改:
// 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以获得更详细的说明