Как расширить ngrx/data с помощью Entity Effects?
При преобразовании приложения для использования управления состоянием ngrx я решил управлять состоянием некоторых моделей с помощью ngrx/data через EntityMaps. Пока это работает нормально, однако, когда все становится немного сложнее, например, на основе данных модели, полученных с удаленного сервера, мне нужны связанные модели (заказы-> продукты или в формате конечной точки RESTGET orders/:id/products
)
Я чувствую себя застрявшим - я знаю, что есть ngrx/effects для запуска действий, которые загружают другие данные при использовании ngrx, и в этом руководстве ngrx/data упоминаются ʻEntityEffects для запуска побочных эффектов с действиями, но кроме этого, документы кажутся в процессе и сейчас мне не очень помогают.
К сожалению, в расширении EntityEffects для настройки получения удаленных данных не так много. Конечно, я мог бы полностью реализовать селекторы, действия, редукторы, эффекты стандартным способом ngrx, но не вся суть ngrx/data в том, чтобы упростить обработку состояния с меньшим количеством шаблонного кода и действовать как оболочка вокруг ngrx, скрывая код по умолчанию / шаблонный код, но при этом предоставляя возможность использовать базовые части?
Поскольку я относительно новичок в ngrx и управлении состоянием в целом, я не знаю, где именно искать лучшие практики или рекомендуемое решение, как решается эта проблема.
Итак, мои вопросы в основном таковы:
- Как я могу одновременно использовать ngrx/data и загружать (связанные) данные модели с помощью ngrx/effects или EntityEffects?
- Где я могу расширить соответствующие службы / классы, не выполняя каждый редуктор / действие вручную и вместо этого позволяя ngrx/data позаботиться об этом?
Я уже искал Stackru, Gitter и спрашивал коллег, но безуспешно - или я могу сделать это намного сложнее, чем должно быть? Если это так, я благодарен за любую помощь.
Примечание: этот вопрос особенно касается ngrx /
1 ответ
Это открытая проблема с github https://github.com/ngrx/platform/issues/1934
Однако я считаю, что есть способ сделать это, не начиная полностью с нуля, используя EntityCacheDispatcher. saveEntities
метод Сохранить с помощью EntityCacheDispatcher.saveEntities().
Чтобы дать вам представление о том, как это работает при использовании по назначению, вот мой эффект порядка сохранения в недавнем проекте.
saveOrder$ = createEffect(() =>
this.actions$.pipe(
ofType(PurchaseOrderActions.saveOrder),
switchMap(() => {
const order$ = this.store.pipe(select(selectHeader));
const orderLines$ = this.store.pipe(select(allLines));
const deletedOrderLines$ = this.store.pipe(select(selectDeletedLines));
return combineLatest([order$, orderLines$, deletedOrderLines$]).pipe(
first(),
switchMap(([order, lines, deletedLines]) => {
const changes: ChangeSetItem[] = [
cif.upsert("PurchaseOrder", order),
cif.upsert("PurchaseOrderLine", lines),
cif.delete("PurchaseOrderLine", deletedLines)
];
return this.entityCacheDispatcher
.saveEntities(changes, `${this.baseURL}order`)
.pipe(
map(changesResponse =>
PurchaseOrderActions.saveOrderSuccess({
header: changesResponse.changes[0]
.entities[0] as PurchaseOrder,
lines: changesResponse.changes[1]
.entities as PurchaseOrderLine[]
})
)
);
})
);
})
)
);
Возможная дорожная карта
- Создайте собственное действие, например, введите
"[OrderProductsPage ONINIT] ONINIT"
- Создать эффект, вызывающий saveEntities
// include in custom action payload and get this id here
const id;
// changeSet with empty changes
const changeSet = {
changes: [],
tag: "CUSTOM_GET_PRODUCTS" // hook for defining custom behaviour
}
this.entityCacheDispatcher.saveEntities(changeSet, `orders/${id}/products`)
- Расширить
EntityCacheDataService
и переопределитьsaveEntities
метод, чтобы сначала проверить, является ли тегCUSTOM_GET_PRODUCTS
в противном случае вызовите super.saveEntities(changeSet, url). Если тегCUSTOM_GET_PRODUCTS
чем вызвать get http и карту каналов для changeSet с помощьюChangeSetOperation.Add
Ссылка на super.saveEntities()
Обновить
Это работает, но немного хитрее, чем мне бы хотелось