6

我目前正在尝试将我的 ngrx 存储转换为使用 ngrx/data 来处理我的实体。我遇到的一个棘手的障碍是处理返回多个实体数据的 API 端点。一个简单的例子——假设我有以下可以从我的 API 中检索到的模型:

export interface Parent {
  id: string;
  name: string;
}

export interface Child {
  id: string;
  name: string;
  parent: string
}

我有以下端点:

/api/parents              #GET (list of parents), POST (create new parent)
/api/parents/<PARENT_ID>  #GET, PATCH, PUSH, DELETE (a single parent)
/api/children             #GET (list of children), POST (create new child)
/api/children/<CHILD_ID>  #GET, PATCH, PUSH, DELETE (a single child)
/api/families             #GET (all parents and children)

/api/families是一个便利函数,它以以下格式返回所有父母和孩子:

{
  parents: Parent[];
  children: Child[];
}

过去,我families为我的 ngrx 存储创建了一个单独的条目,其中仅包含加载/加载参数,然后是一组LoadFamilies从服务器获取数据的操作。然后我将这些操作包含在我的父母和孩子存储减速器中,并适当地对它们采取行动。我现在要做的是将这个额外的 reducer 添加到我现有的 ngrx/data 控制实体中。关于如何解决这个问题的任何想法/示例代码?

4

1 回答 1

2

扩展DefaultDataServicehttps://ngrx.io/guide/data/entity-dataservice#custom-entitydataservice

在管道内将嵌套数据映射到实体(我使用 normalizr)

EntityActionFactory as eaFactory然后使用您认为合适的方式调度实体缓存操作以更新存储

父 <--> ConcreteRecordHeader 的子 <--> ConcreteRecordLoad 示例

  getById(key: string | number): Observable<ConcreteRecordHeader> {
    return super.getById(key).pipe(
      map((denorm: any) =>
        this.categoryCacheService.normalizeCategory([denorm])
      ),
      tap((norm: NormalizedCategories) => this.mergeQuerySet(norm)),
      map((norm: NormalizedCategories) => this.pickEntities(norm)[0])
    ) as Observable<ConcreteRecordHeader>;
  }

  protected mergeQuerySet(norm: NormalizedCategories) {
    console.log("⚠️ Merging server data ⚠️");
    const options: EntityActionOptions = {
      mergeStrategy: MergeStrategy.PreserveChanges
    };
    const data = norm.entities.concreteRecordLoads
      ? Object.values(norm.entities.concreteRecordLoads)
      : [];
    const action = this.eaFactory.create(
      "ConcreteRecordLoad",
      EntityOp.SAVE_UPSERT_MANY_SUCCESS,
      data,
      options
    );
    this.entityCacheDispatcher.dispatch(action);
  }

  protected pickEntities(norm: NormalizedCategories) {
    return (norm.entities.concreteRecordHeaders
      ? Object.values(norm.entities.concreteRecordHeaders)
      : []) as ConcreteRecordHeader[];
  }

遗憾this.entityCacheDispatcher.mergeQuerySet()的是,它没有使用自然 API 的 mergeStrategy。我计划为此提交 PR。

于 2020-02-28T14:58:19.600 回答