RxJS Observable和正确的方式来构建过滤列表

问题描述:

我已经经历了一堆教程,做了演示等..但我仍然无法包围我的头正确的方式来做到这一点与Observables ...RxJS Observable和正确的方式来构建过滤列表

基本上是我有(在角)是在我的组件2个可变阵列,一个显示列表和项目的fullList ...模板确实上DisplayList中的ngFor。在屏幕上

过滤器调用在清除显示列表组件过滤功能,然后通过fullList循环,如果应用过滤器,它推动它显示列表 - 在屏幕上给人一种实时列表过滤效果...

我知道这是解决这个问题的错误方法,但是我无法将自己的头围绕着需要使用observables做到这一点的架构/模式。我是否会创建一个主列表并根据组件私有属性对其执行.filter()?对于一个返回带有.filter的可观察列表的方法,我该如何做ngFor?

在此先感谢。

+0

除非有一些功能你不能实现,除非你使用observables我认为你的方法听起来不错。您可以为displayList创建一个BehaviorSubject,例如'displayList = new BehaviorSubject([])'并用'displayList.next(newDisplayList)'更新它。然后,您可以在displayFormat | async“'中用'* ngFor =”项在ngFor中绑定它。但我不一定会看到这种方法的好处 – rob

是的,是的,不,是,否......换句话说:没有正确的答案,这取决于。 (在你的个人喜好,在一般使用情况下,您的应用程序的现有的架构,等。等...)


过滤控制器

在你的情况,可能并不需要rxjs,尽管如果可能的话应该避免使用可变对象/数据,所以使用.filter的想法将成为这里的一种方式。


自管

另一种方式去将实现自定义管道和模板将数据直接进行过滤:

<div *ngFor="let item of fullList | customFilterPipe:filterSettings">...</div> 

的RxJS路

既然你问了rxjs路,这里是我会怎么做:

filterSettings$: BehaviorSubject<IFilterData> = new BehaviorSubject(INITIAL_FILTER_SETTINGS); // this is updated with filterSettings$.next(newFilterSettings) 
fullList$: BehaviorSubject<IData[]> = new BehaviorSubject([]); // updated through fullList$.next(newFullList); 
displayList$ = Observable.combineLatest(this.fullList$, this.filterSettings$) 
    .map(([list, filterSettings]) => { 
     return list.filter(/* your custom filter based on the filterSettings... */); 
    }); 

这将自动更新displayList$每当filterSettings$fullList$变化。

要在templare使用它,你可以使用async - 管:

<div *ngFor="let item of displayList$ | async">...</div> 

但再次:任何这些解决方案,以及你目前执行的可能是一个完全有效的实现给定情况。

+0

谢谢,这正是我一直在寻找的 –

在RxJS 5本最佳候选是combineLatest()操作者(它有静态和实例方法变体),当任何其源观测量的发射值,该值调用其选择器的功能。

let userInput$ = Observable.from(['a', 'ac', 'aca', 'acarp']) 
    .concatMap(char => Observable.of(char).delay(500)) 
    .startWith(null); 

let list$ = Observable.of(['abstemious', 'abstentious', 'abulia', 'abut', 'aby', 'acalculia', 'acarophobia', 'acarpous', 'accidence', 'accismus', 'acclamation']); 

let filteredList$ = Observable.combineLatest(list$, userInput$, (list, filterString) => { 
    if (filterString) { 
     // Note that this is Array.filter() method, not an RxJS operator 
     return list.filter(name => name.indexOf(filterString) === 0); 
    } 
    return list; 
    }); 


filteredList$.subscribe(val => console.log(val)); 

见现场演示:https://jsbin.com/jihuxu/2/edit?js,console

这是模拟的情况下每500ms用户键入一个字符,并相应地过滤list$。请注意,list$也可以发出一个新的数组,可以立即进行过滤。

需要注意的一件重要的事情是,每个源Observable必须发出至少一个值,然后.combineLatest()才能发出每个更改。这就是为什么我也有startWith(null),为了确保选定的过滤器在开始时是null