[英]Rxjs filter observable with array of filters
我在这里是因为我在使用 Rxjs 进行过滤时遇到问题。 我正在尝试使用一系列过滤器过滤可观察到的产品...
让我解释一下,我想将过滤结果设置为过滤产品。 对于过滤,对于每个过滤器,我必须检查产品的过滤器数组是否包含过滤器的名称,以及产品值数组是否包含过滤器 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));
}
}
提前非常感谢您:-)。
我认为您必须将selectedFilters
更改为BehaviorSubject并将其与products$
observable 一起使用。 有combineLatest function 监听多个 observables 的最新值并返回一个数组
例子
window.products$ = rxjs.of([ { id: 1, name: "product 1", category: { id: 1, name: 'test' }, filters: [ { name: "test1", values: [1] } ], url: '/assets/test1.png' }, { id: 2, name: "product 2", category: { id: 1, name: 'test' }, filters: [ { name: "test2", values: [2] } ], url: '/assets/test2.png' } ]) window.filteredProducts$ = null; window.selectedFilters = new rxjs.BehaviorSubject([]) function filterProducts() { filteredProducts$ = rxjs.combineLatest(products$, selectedFilters).pipe( rxjs.operators.map( ([products, filters]) => products.filter( product => product.filters.some(filter => filters.some(([filterName]) => filterName === filter.name.toLowerCase()) && filter.values.some(value => filters.some(([, filterId]) => filterId === value)) ) ) ) ); filteredProducts$.subscribe(res => console.log('filtered:', res)); } filterProducts() window.selectedFilters.next([...window.selectedFilters.value, ['test1', 1]]); window.selectedFilters.next([...window.selectedFilters.value, ['test2', 2]]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>
您的代码看起来不错,但可以稍作修改。 首先,我会清理谓词,您可以使用lodash intersectionWith
function 相交两个具有不同值的 arrays。
此外,您可以使用mergeAll
运算符逐个过滤器迭代过滤器,这使得它看起来不那么嵌套。
总的来说,它应该看起来像这样:
products$
.pipe(
mergeAll(),
filter(
product =>
_.intersectionWith(
product.filters,
selectedFilters,
(filter, [name, id]) =>
filter.name.toLowerCase() === name && filter.values.includes(id)
).length > 0
)
)
.subscribe(console.log);
您可以在此处运行完整的示例代码
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.