2017-03-02 56 views
3

我已經經歷了一堆教程,做了演示等..但我仍然無法包圍我的頭正確的方式來做到這一點與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

回答

2

是的,是的,不,是,否......換句話說:沒有正確的答案,這取決於。 (在你的個人喜好,在一般使用情況下,您的應用程序的現有的架構,等。等...)


過濾控制器

在你的情況,可能並不需要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

謝謝,這正是我一直在尋找的 –

2

在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