Прочитав и попробовав все до сих пор, чтобы обновить мои additionalCollectionStates до моей EntityCollection (на основе небольшой информации из документов, этот вопрос SO , этот другой вопрос SO , еще один вопрос SO и проблема из репозитория github ) Я застрял в том, что должно быть довольно распространенной задачей, и не было никаких проблем до использования ngrx: сортировка сохраненной коллекции сущностей с ngrx. Поиск решений возвращает меня к тем же 10 ссылкам, которые я уже видел 5 раз, и большинство примеров либо слишком базовые c, либо устарели, либо вообще не используют ngrx / data, либо на подобные вопросы вообще нет ответов.
Среда : Angular 9.1.7, ngrx 9.1.2, macOS 10.14.6
Цель
Добавить и обновите свой additionalCollectionState
до моего EntityCollection, как описано в документации для сортировки и разбивки на страницы. Я не получаю sortQuery Properties (sortField, sortDirection) с сервера, а скорее устанавливаю его в моем GUI и сортирую коллекцию на их основе. Я знаю, что в EntityMetadataMap существует настройка sortComparer
, но она недостаточно гибкая для моих средств, я хочу динамически сортировать коллекции в разных MatTables в приложении. Это дополнительное свойство следует обновлять всякий раз, когда изменяется порядок / поле сортировки в MatTable.
То, что я достиг до сих пор:
Способ ngrx / data для additionalCollectionState как описано выше работает , моя коллекция инициализирована данными, которые я предоставил в EntityMetadataMap. Однако обновление свойств пользовательской коллекции не работает так, как я понял из документации. Поскольку я не получаю свойство sortQuery с сервера, ResultsHandler не вызывается.
Я подошел к этой проблеме двумя способами: а) с помощью методов ngrx и ngrx / entity и b ) способ ngrx / data, пытаясь расширить настраиваемый EntityCollectionReducer
a) Мне удалось создать настраиваемое действие и настраиваемый редуктор и обновить свойство состояния , но а не ранее определенное свойство коллекции . Мое действие в основном:
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 Collection с Свойство sortQuery , как видно на этом снимке экрана: and updates it also according to the changed sortQuery property. However, I would prefer using the already initialized sortQuery property in the Resource entityCache collection (yeah, I also tried adding it to the entityCache feature with StoreModule.forFeature('entityCache', reducers)
ignore that):
введите описание изображения здесь
b) Таким образом, другой подход заключался в использовании 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 .
У меня есть ощущение, что с подходом б) я могу быть на правильном пути, однако я застрял из-за отсутствия документации и примеров того, как решить эту проблему - есть ли кто-нибудь, кто может чтобы помочь мне?
Если требуются дополнительные сведения, я с радостью их предоставлю, а если что-то неясно, поскольку английский sh не является моим родным языком, я с удовольствием поясню, и, если необходимо, постараюсь предоставить упрощенный пример stackblitz. Спасибо!