我正在尝试使用一系列过滤器来过滤可观察产品,但是我真的不知道如何。
让我解释一下,我想将过滤的结果设置为filteredProducts。 对于过滤,我必须针对每个过滤器检查产品的过滤器数组是否包含过滤器的名称以及产品值数组的过滤器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));
}
}
在此先感谢您:-)。
答案 0 :(得分:0)
这是一个stackblitz,上面有一个有效的示例。
总结一下:
combineLatest
将它们组合成一个可观察的状态: 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$
发出新值时,我们也会对其进行更新。
请注意,{Each combineLatest
直到可观察到的至少发射一次后才会发射。因此,如果您的“ selectedFilters”一开始没有发出任何东西,则可以使用startWith
运算符创建一个具有起始值的可观察对象。这样可以确保combineLatest
会在products$
发出值后立即发出值。
我还将过滤代码移到了静态函数中
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
。