Search code examples
angularngrxngrx-storengrx-entity

Receiving an array with a specific key using ngrx/selector and ngrx/entities


How can I use the selector to get data only with a certain key?

That is, I have 4 menus, each with a specific catalogCode, the user gets a list for a specific menu from the server on click. Each element of this list has an id = code + catalogCode. That is, the catalogCode of all elements of this menu will be the same. So how do I get a list of items for a particular catalogCode from the store?

I'm trying to do so: selectByCatalogCode

export const selectCatalogItemState: MemoizedSelector<object, State> = createFeatureSelector('CatalogItem');
export const selectCatalogItemAll: MemoizedSelector<object, CatalogItem[]> = createSelector(selectCatalogItemState, selectAll);
export const selectByCatalogCode = () => createSelector(selectCatalogItemAll, (entities: CatalogItem[], props: { catalogCode: string }) => entities[props.catalogCode]);

But this does not work when used in a component, always displays an undefined value

  getCatalogItems(catalogCode: string) {
    this.catalogItemStore.dispatch(new CatalogItemStoreAction.LoadByCatalog({catalogCode: catalogCode}));
    this.catalogItemStore.select(CatalogItemStoreSelector.selectByCatalogCode(), {catalogCode: catalogCode}).subscribe(
      a => console.log(a)
    );
  }

catalog-item.ts

export class CatalogItem {
  constructor(public code: string,
              public catalogCode: string,
              public title: string,
              public data: object) {
  }
}

I have provided only part of the code. If necessary, I can provide the code of the entire store.

effect.ts

  @Effect()
  getCatalogEffect$: Observable<Action> = this.action$
    .pipe(
      ofType<featureAction.GetByCatalog>(featureAction.ActionTypes.GET_BY_CATALOG),
      switchMap(action => this.store.select(CatalogItemStoreSelector.selectByCatalogCode(action.payload.catalogCode))
        .pipe(
          take(1),
          filter(catalogItems => !catalogItems),
          map(() => new featureAction.LoadByCatalog({catalogCode: action.payload.catalogCode})),
        )
      )
    );
  @Effect()
  loadByCatalog$: Observable<Action> = this.action$
    .pipe(
      ofType<featureAction.LoadByCatalog>(featureAction.ActionTypes.LOAD_BY_CATALOG),
      switchMap(action => this.catalogItemService.listByCatalog(action.payload.catalogCode)
        .pipe(
          map(catalogItems => new featureAction.LoadByCatalogSuccess({catalogItems: catalogItems})),
          catchError(error => of(new featureAction.LoadByCatalogError({error: error}))),
        )
      )
    );

catalogs-list.component.ts

  getCatalogItems(catalogCode: string) {
    this.catalogItemStore.dispatch(new CatalogItemStoreAction.GetByCatalog({catalogCode: catalogCode}));
  }

Solution

  • In your selector, if you want to get the object which match your catalogCode, use a filter.

    TS:

    this.catalogItemStore.select(CatalogItemStoreSelector.selectByCatalogCode(catalogCode)).subscribe(
          a => console.log(a)
        );
    

    Selector:

    export const selectByCatalogCode = (catalogCode: string) => createSelector(selectCatalogItemAll, (entities: CatalogItem[]) => entities.filter((item: CatalogItem) => item.catalogCode === catalogCode));