繁体   English   中英

Rxjs 滤波器可通过滤波器阵列观察

[英]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));
    }
}

这是一个产品object的结构这是产品对象的结构

这是 selectedFilters 的结构在此处输入图像描述

提前非常感谢您:-)。

我认为您必须将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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM