angulartypescriptrxjsakita

How to dynamically query entities from an akita entity store


I have an entity like this

interface IDevice {
  id: string;
  name: string;
  brand: string;
  plan: 'contract' | 'unlocked';
}

and an entity store

interface DevicesState extends EntityState<IDevice> {
  selectedBrand: string | undefined;
  selectedPlan: 'contract' | 'unlocked';
}

And I want to query and filter the entities based on the brand selected.

My only attempt was this

  selectedBrand$ = this.select('selectedBrand');
  selectedPlan$ = this.select('selectedPlan');
  devices$ = this.selectedBrand$ 
    ? this.selectAll({
        filterBy: [
         entity => entity.brand === this.selectedBrand$,
         entity => entity.plan === this.selectedPlan$,
        ]
      })
    : this.selectMany([]);

This will not work since this.selectedBrand$ is an observable. How do I select the devices based on two outer state values?


Solution

  • You can use switchMap to first observe the selected brand and then switch to the store select based on the selected brand:

    selectedBrand$ = this.select('selectedBrand');
    devices$ = this.selectedBrand$
      .pipe(
          switchMap(brand => brand 
              ? this.selectAll({
                    filterBy: entity => entity.brand === brand
              }) 
              : this.selectMany([])
          )
      );
    

    When you want to combine two observables, you can use combineLatest:

      devices$ = combineLatest(this.selectedBrand$, this.selectedPlan$)
        .pipe(
          switchMap(([brand, plan]) => this.selectAll({
              filterBy: [
                brand ? entity => entity.categories.map(x => x.name).includes(brand) : null,
                plan ? entity => entity.plan_tab === plan : null
              ].filter(x => x !== null)
          })
        );