簡體   English   中英

Angular rxjs 濾波器可觀察

[英]Angular rxjs filter observable

我正在嘗試使用一系列過濾器過濾可觀察到的產品,但我真的不知道如何..

讓我解釋一下,我想將過濾結果設置為過濾產品。 對於過濾,對於每個過濾器,我必須檢查產品的過濾器數組是否包含過濾器的名稱,以及產品值數組是否包含過濾器 ID。

目前,過濾器有效,但僅適用於最后選擇的過濾器,我想用我的 selectedFilters 數組中的所有過濾器過濾產品列表。 我可以有一個或多個過濾器。

StackBlitz

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 的結構在此處輸入圖像描述

提前非常感謝您:-)。

這是一個堆棧閃電戰,其中包含一個有效的示例。

把它們加起來:

  1. 我們監聽產品和過濾器的變化,並使用combineLatest將它們組合成一個單獨的 observable:
    const productsAndFilters: Observable<[Product[], ProductFilter[]]> = combineLatest([
      this.products$,
      this.filters$.pipe(startWith(initialFilters)),
    ]);
  1. 然后我們將 pipe 組合的 observable 轉換為實際執行過濾工作的 function
    this.filteredProducts$ = productsAndFilters.pipe(
      map(([products, filters]) => {
        return AppComponent.filterProducts(products, filters);
      }),
    )
  1. 每次products$發出一個新值時,我們都會更新filteredProducts$ 每次filters$發出一個新值時,我們也會更新它們。

  2. 請注意,在每個 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM