Прочитав и попробовав все до сих пор, чтобы обновить мои additionalCollectionStates до моей EntityCollection (на основе небольшой информации из документов, этот вопрос SO, этот другой вопрос SO, еще один вопрос SO и проблема из репозитория github) Я застрял в том, что должно быть довольно распространенной задачей, и не было никаких проблем до использования ngrx: сортировка сохраненной коллекции сущностей с помощью ngrx. Поиск решений возвращает меня к тем же 10 ссылкам, которые я уже видел 5 раз, и большинство примеров либо слишком просты, либо устарели, либо вообще не используют ngrx / data, либо на аналогичные вопросы вообще нет ответов.
Среда: Angular 9.1.7, ngrx 9.1.2, macOS 10.14.6.
Цель
Добавить и обновить собственный additionalCollectionState
в мою коллекцию EntityCollection, как описано в документации для сортировки и разбивка на страницы. Я не получаю свойства sortQuery (sortField, sortDirection) с сервера, а устанавливаю их в своем графическом интерфейсе и сортирую коллекцию на их основе. Я знаю, что в EntityMetadataMap существует параметр sortComparer
, но он недостаточно гибкий для моих средств, я хочу динамически сортировать коллекции в разных таблицах MatTables в приложении. Это дополнительное свойство следует обновлять всякий раз, когда изменяется порядок / поле сортировки в MatTable.
Чего я уже достиг:
Способ ngrx / data для additionalCollectionState, как описано выше, работает, моя коллекция инициализируется данными, которые я предоставил в EntityMetadataMap. Однако обновление свойств настраиваемой коллекции не работает так, как я понял из документации. Поскольку я не получаю свойство sortQuery с сервера, ResultsHandler не вызывается.
Я подошел к этой проблеме двумя способами: а) используя методы ngrx и ngrx / entity и б) способ ngrx / data, пытаясь расширить пользовательский EntityCollectionReducer
а) Мне удалось создать настраиваемое действие и настраиваемый редуктор и обновить свойство состояния, но не ранее определенное свойство коллекции. Мои действия в основном таковы:
export const selectResourceSortQuery = createAction('[Resource] Get Last Sort Query', props<{ sortQuery: any }>());
Вызывается из службы с:
this.store.dispatch(selectResourceSortQuery({ sortQuery }));
и обрабатывается в редукторе:
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { Action, createReducer, on } from '@ngrx/store';
import * as ResourceActions from './resource.actions';
import { Resource } from 'src/app/sdk';
export interface State extends EntityState<Resource> {
// additional state property
sortQuery: any | null;
}
export const adapter: EntityAdapter<Resource> = createEntityAdapter<Resource>();
export const initialState: State = adapter.getInitialState({
// additional entity state properties
sortQuery: {
sortDirection: 'asc',
sortField: 'product'
},
});
export const resourceReducer = createReducer(
initialState,
on(ResourceActions.selectResourceSortQuery, (state, { sortQuery }) => {
console.log(`REDUCER called`);
return { ...state, sortQuery };
}),
);
export function reducer(state: State | undefined, action: Action) {
return resourceReducer(state, action);
}
Редюсеры экспортируются в redurs / index.ts:
import {
ActionReducer,
ActionReducerMap,
createFeatureSelector,
createSelector,
MetaReducer
} from '@ngrx/store';
import { environment } from 'src/environments/environment';
import * as fromResourceReducers from 'src/app/store/entities/resource/resource.reducer';
export interface State {
}
export const reducers: ActionReducerMap<State> = {
resourceSort: fromResourceReducers.reducer
};
export const metaReducers: MetaReducer<State>[] = !environment.production ? [] : [];
В app.module это настроено как:
StoreModule.forRoot(reducers, {
metaReducers: [
ngrxEntityRelationshipReducer //ignore this
],
runtimeChecks: {
strictStateImmutability: true,
strictActionImmutability: true
}
}),
Это создает коллекцию resourceSort со свойством sortQuery, как видно на этом снимке экрана: и обновляет его также в соответствии с измененными sortQuery свойство. Однако я бы предпочел использовать уже инициализированное свойство sortQuery в коллекции Resource entityCache (да, я также пытался добавить его в функцию entityCache, StoreModule.forFeature('entityCache', reducers)
игнорируя это):
б) Таким образом, другой подход заключался в использовании EntityCollectionReducerRegistry в app.module:
import { resourceReducer } from './store/entities/resource/resource.reducer';
// does not work: resourceReducer is of type ActionReducer<State, Action> and the same as posted above (with the added handling of the sortQuery property), and apparently what this function expects
entityCollectionReducerRegistry.registerReducer('Resources', resourceReducer);
// this does work, but just creates the basic default entity collection reducer without my custom sortQuery handling
entityCollectionReducerRegistry.registerReducer('Resources', entityCollectionReducerFactory.create('resources'))
Из документов:
Entity Reducer - это главный редуктор для всех коллекций сущностей в кэше сохраненных сущностей. В библиотеке нет именованного типа редуктора сущностей. Скорее, он полагается на метод EntityCacheReducerFactory.create () для создания этого редуктора, которым является NgRx ActionReducer ‹EntityCache, EntityAction›.
У меня есть ощущение, что с подходом б) я могу быть на правильном пути, однако я застрял из-за отсутствия документации и примеров того, как справиться с этой проблемой - может ли кто-нибудь мне помочь?
Если требуются дополнительные сведения, я с радостью их предоставлю, а если что-то неясно, поскольку английский не является моим родным языком, я с удовольствием поясню, и, если необходимо, попытаюсь предоставить упрощенный пример stackblitz. Спасибо!