создать селектор для объекта ngrx / data - PullRequest
2 голосов
/ 28 октября 2019

У меня есть состояние, и я хотел бы создать селекторы из сущностей ngrx / data.

import {
  Action,
  ActionReducer,
  ActionReducerMap,
  createFeatureSelector,
  createSelector,
  MetaReducer
} from '@ngrx/store';
import {environment} from '../../environments/environment';
import * as fromRouter from '@ngrx/router-store';
import * as fromDrawer from './drawer';
import {InjectionToken} from '@angular/core';
import {NavigationItem} from '../models/navigation-item';

export interface State {
  router: fromRouter.RouterReducerState<any>;
  drawerNavigationItems: fromDrawer.State;
}

export const ROOT_REDUCERS = new InjectionToken<ActionReducerMap<State, Action>>('Root reducers token', {factory: () => ({
    router: fromRouter.routerReducer,
    drawerNavigationItems: fromDrawer.reducer,
  }),
});

export const metaReducers: MetaReducer<State>[] = !environment.production ? [] : [];

export const selectRouter = createFeatureSelector<
  State,
  fromRouter.RouterReducerState<any>
  >('router');

const {
  selectQueryParams,    // select the current route query params
  selectQueryParam,     // factory function to select a query param
  selectRouteParams,    // select the current route params
  selectRouteParam,     // factory function to select a route param
  selectRouteData,      // select the current route data
  selectUrl,            // select the current url
} = fromRouter.getSelectors(selectRouter);

export const selectRouteId = selectRouteParam('id');
export const selectStatus = selectQueryParam('status');


// Drawer

export const selectDrawerNavigationItems = (state: State) => state.drawerNavigationItems.items as NavigationItem[];

Как использовать предопределенные селекторы или написать свой собственный для сущностей или служб, полученных изngrx / data?

В качестве примера я хотел бы создать селектор, который выбирает все объекты «Сообщество», а затем, на шаге 2, выберите 1 с помощью selectRouteId. Если вы представляете маршрут /communities/:id, selectRouteId возвращает идентификатор, и теперь я хотел бы получить данные из CommunityService и использовать селектор, созданный или каким-либо образом импортированный и использованный на шаге 1, и вернуть результат, 1 Community с идентификатором selectRouteId, поэтому позже я смогу сделать что-то вроде this.store.dispatch(selectCommunityByCurrentRouteId);

Этот вопрос относится к @ ngrx / data.

Ответы [ 3 ]

1 голос
/ 30 октября 2019

См. https://github.com/peterbsmith2/platform/blob/b2f17bfcc987bf63d10dd207263c0ca2a2e44373/projects/ngrx.io/content/guide/data/extension-points.md#custom-selectors.

/* src/app/reducers/index.ts */
import * as fromCat from './cat.reducer';
import { Owner } from '~/app/models'

export const ownerSelectors = new EntitySelectorsFactory().create<Owner>('Owner');

export interface State {
  cat: fromCat.State;
}

export const reducers: ActionReducerMap<State> = {
  cat: fromCat.reducer
};

export const selectCatState = (state: State) => state.cat;

export const {
  selectAll: selectAllCats
} = fromCat.adapter.getSelectors(selectCatState);

export const selectedCatsWithOwners = createSelector(
  selectAllCats,
  ownerSelectors.selectEntities,
  (cats, ownerEntities) => cats.map(c => ({
    ...c,
    owner: ownerEntities[c.owner]
  }))
);
1 голос
/ 30 октября 2019

дополнительный ответ, чтобы конкретно ответить на мой собственный вопрос, вот как выглядит сейчас Redurs / index.ts

import {
  Action,
  ActionReducer,
  ActionReducerMap,
  createFeatureSelector,
  createSelector,
  MetaReducer
} from '@ngrx/store';
import {environment} from '../../environments/environment';
import * as fromRouter from '@ngrx/router-store';
import * as fromDrawer from './drawer';
import {InjectionToken} from '@angular/core';
import {NavigationItem} from '../models/navigation-item';
import {EntitySelectorsFactory} from '@ngrx/data';
import {Community} from '../models/community';

export interface State {
  router: fromRouter.RouterReducerState<any>;
  drawerNavigationItems: fromDrawer.State;
}

export const ROOT_REDUCERS = new InjectionToken<ActionReducerMap<State, Action>>('Root reducers token', {factory: () => ({
    router: fromRouter.routerReducer,
    drawerNavigationItems: fromDrawer.reducer,
  }),
});

export const metaReducers: MetaReducer<State>[] = !environment.production ? [] : [];

export const selectRouter = createFeatureSelector<
  State,
  fromRouter.RouterReducerState<any>
  >('router');

const {
  selectQueryParams,    // select the current route query params
  selectQueryParam,     // factory function to select a query param
  selectRouteParams,    // select the current route params
  selectRouteParam,     // factory function to select a route param
  selectRouteData,      // select the current route data
  selectUrl,            // select the current url
} = fromRouter.getSelectors(selectRouter);

export const selectRouteId = selectRouteParam('id');
// export const selectStatus = selectQueryParam('status');

// Data

export const communitySelectors = new EntitySelectorsFactory().create<Community>('Community');

export const selectCommunityByRouteId = createSelector(
  selectRouteId,
  communitySelectors.selectEntities,
  (id, communities) => communities.find(c => c.id === id)
);


// Drawer

export const selectDrawerNavigationItems = (state: State) => state.drawerNavigationItems.items as NavigationItem[];

Вы создаете селектор для модели Сообщества с помощью

export const communitySelectors = new EntitySelectorsFactory().create<Community>('Community');

и затем вы объединяете эти два и возвращаете 1 Community по идентификатору маршрута.

export const selectCommunityByRouteId = createSelector(
  selectRouteId,
  communitySelectors.selectEntities,
  (id, communities) => communities.find(c => c.id === id)
);

действительно просто, вы выбираете входные потоки, предоставляете функцию проекции и возвращаете результат.

Позже, в компоненте

export class OneCommunityComponent implements OnInit {
  community$: Observable<Community>;
  constructor(
    private store: Store<State>,
  ) {
  this.community$ = this.store.select(selectCommunityByRouteId);
  }
}
0 голосов
/ 28 октября 2019

Лучшее решение в вашей ситуации - это очень хорошие адаптеры. Вы можете посмотреть здесь: https://ngrx.io/guide/entity/adapter

Вы можете удалить, добавить, обновить любой объект в вашем магазине с этим и очень легко. Вам просто нужно расширить свое состояние :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...