输入数组过滤后,角度异步管道不会刷新结果

时间:2019-03-19 11:39:22

标签: javascript angular observable

在父组件中,我有一个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))))
    );
  }

,并且我不需要再次订阅,视图中的结果根据用户键入的搜索词而变化。这是正确的方法吗?

1 个答案:

答案 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)">
...

另外,最好添加debounceTimedistinctUntilChanged,以获得更好的用户体验和更少的搜索请求。

有关详细信息,请参见full example。另外,请参考this article以获得更详细的说明