NGRX; Как применить фильтр к данным адаптера

У меня есть этот фрагмент кода, к которому я хочу применить фильтр. Состояние использует EntityState и Adapter. getAllObjects необходимо получить категории с parentId, равным 13, а getAllTextures получит оставшееся.

import { Category } from './models/category';
import { createFeatureSelector, createSelector } from '@ngrx/store';
import { AppState } from './app-state';
import { EntityState } from '@ngrx/entity';
import * as fromCategory from './services/reducers/category.reducer';

export interface CategoriesState extends EntityState<Category> {
    allCategoriesLoaded: boolean;
}

const getCategories = createFeatureSelector<AppState, CategoriesState>('categories');

export const getAllObjects = createSelector(getCategories, fromCategory.selectAll); // filter(x => x.parentId === 13)
export const getAllTextures = createSelector(getCategories, fromCategory.selectAll); // filter(x => x.parentId !== 13)
export const getAllCategoriesLoaded = createSelector(getCategories, state => state.allCategoriesLoaded);

а это редуктор:

import {createReducer, on, State} from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { Category } from 'src/app/models/category';
import { RefreshCategoryDone, CategoryActionTypes, CategoryActions } from '../actions/category.actions';
import { CategoriesState } from 'src/app/categories-state';


export const categoryAdapter: EntityAdapter<Category> = createEntityAdapter<Category>();
export const initialState: CategoriesState = categoryAdapter.getInitialState({allCategoriesLoaded : false});

export function categoryReducer(state = initialState, action: CategoryActions) {
  switch (action.type) {
      case CategoryActionTypes.LoadCategories:
      categoryAdapter.addMany(action.payload, state);
      break;
    default:
      return state;
  }
}

export const {
  selectAll,
  selectEntities,
  selectIds,
  selectTotal
} = categoryAdapter.getSelectors();

Можно ли выбрать данные с адаптера по условию? Если да, то как?


person amin mohammadi    schedule 05.01.2020    source источник


Ответы (2)


Вот несколько простых шагов, чтобы это настроить:

1) добавьте свойство selectedId в ваше состояние и установите для начального состояния значение null

   export interface State extends EntityState<Category> {
       selectedCategoryId: string | null;
   }

   export const adapter: EntityAdapter<Category> = createEntityAdapter<Category>({
      selectId: (category: Category) => category.id,
      sortComparer: false,
   });

   export const initialState: State = adapter.getInitialState({
      selectedCategoryId: null,
   });

2) Добавить действия для установки выбранного ID

   // in the reducer, the action does following:
   on(ViewReportPageActions.selectCategory, (state, { id }) => ({
      ...state,
      selectedCategoryId: id,
   })),

3) добавить селектор для selectedId в редукторе

    export const getSelectedId = (state: State) => state.selectedReportId;

4) добавьте селектор в свой файл FeatureSelector, здесь вы добавляете фильтр

// you've implemented another name for you Feature Selector here
export const getDataState = createFeatureSelector<State, DataState>('data');

export const getCategoryEntitiesState = createSelector(
  getDataState,
  state => state.categories
);

export const getSelectedCategoryId = createSelector(
  getCategoryEntitiesState,
  fromCategorys.getSelectedId
);

export const getSelectedCategory = createSelector(
  getCategoryEntities,
  getSelectedCategoryId,
  (entities, selectedId) => {
    if (selectedId != "0"){
      return selectedId && entities[selectedId];
    } else {
      //this is what I use, when I want to create a new category. 
      //I set the selectedId to 0 which indicitates I'm creating a new one
      return selectedId && generateMockCategory(); 
    }
  }
);

export const getNotSelectedCategory = createSelector(
  getCategoryEntities,
  getSelectedCategoryId,
  (entities, selectedId) => {
    // You'll have to test this...
    return entities.filter(e => e.id !== selectedID);
  }
);

примеры страниц:

person James D    schedule 06.01.2020

Нашел ответ:

import { Category } from './models/category';
import { createFeatureSelector, createSelector } from '@ngrx/store';
import { AppState } from './app-state';
import { EntityState } from '@ngrx/entity';
import * as fromCategory from './services/reducers/category.reducer';
import { map } from 'rxjs/operators';

export interface CategoriesState extends EntityState<Category> {
    allCategoriesLoaded: boolean;
}

const getCategories = createFeatureSelector<AppState, CategoriesState>('categories');

export const getAllCategories = createSelector(getCategories, fromCategory.selectAll);
export const getAllObjects = createSelector(getAllCategories, (categories) => categories.filter(x => x.categoryId !== 13));
export const getAllTextures = createSelector(getAllCategories, (categories) => categories.filter(x => x.categoryId === 13));
export const getAllCategoriesLoaded = createSelector(getCategories, state => state.allCategoriesLoaded);
person amin mohammadi    schedule 05.01.2020