[英]Angular rxjs filter observable
我正在嘗試使用一系列過濾器過濾可觀察到的產品,但我真的不知道如何..
讓我解釋一下,我想將過濾結果設置為過濾產品。 對於過濾,對於每個過濾器,我必須檢查產品的過濾器數組是否包含過濾器的名稱,以及產品值數組是否包含過濾器 ID。
目前,過濾器有效,但僅適用於最后選擇的過濾器,我想用我的 selectedFilters 數組中的所有過濾器過濾產品列表。 我可以有一個或多個過濾器。
export class ProductsFilterComponent extends BaseComponent implements OnInit {
@Select(FiltersState.getAllFilters) filters$: Observable<any>;
@Input() products$: Observable<Product[]>;
filteredProducts$: Observable<Product[]>;
public selectedFilters = [];
constructor(
private store: Store) { super(); }
ngOnInit() {
this.store.dispatch(new GetAllFilters());
}
private filterProducts() {
this.filteredProducts$ = this.products$.pipe(
map(
productsArr => productsArr.filter(
p =>
p.filters.some(f => this.selectedFilters.some(([selectedF]) => selectedF === f.name.toLowerCase()) // Filter name
&& f.values.some(value => this.selectedFilters.some(([, filterId]) => filterId === value)) // Filter id
)
)
)
);
this.filteredProducts$.subscribe(res => console.log('filtered:', res));
}
}
提前非常感謝您:-)。
這是一個堆棧閃電戰,其中包含一個有效的示例。
把它們加起來:
combineLatest
將它們組合成一個單獨的 observable: const productsAndFilters: Observable<[Product[], ProductFilter[]]> = combineLatest([
this.products$,
this.filters$.pipe(startWith(initialFilters)),
]);
this.filteredProducts$ = productsAndFilters.pipe(
map(([products, filters]) => {
return AppComponent.filterProducts(products, filters);
}),
)
每次products$
發出一個新值時,我們都會更新filteredProducts$
。 每次filters$
發出一個新值時,我們也會更新它們。
請注意,在每個 observable 至少發出一次之前, combineLatest
不會發出。 出於這個原因,如果您的“selectedFilters”在開始時沒有發出任何內容,您可以使用startWith
運算符創建一個具有起始值的 observable。 這確保了combineLatest
將在products$
發出一個值時立即發出一個值。
我還將過濾代碼移動到 static function 中:
private static filterProducts(products: Product[], filters: ProductFilter[]) {
// we can combine filters into a single function
// so that the code a tiny bit more readable
const matchesAllFilters = (product: Product) => filters.every(
([filterName, filterValue]) => product.filters
.some(f => f.name === filterName &&
f.values.some(value => value === filterValue))
);
return products.filter(matchesAllFilters);
}
在我的示例中,我假設您希望滿足所有過濾器。 如果您希望“至少一個”過濾器得到滿足,您可以將filters.every
更改為filters.some
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.