1

我已经习惯了ngrx-store,但是为了摆脱样板,我决定使用ngrx-data。Ngrx-data 文档有一点限制,我很难找到实现 odata 模式的方法。

正如你在这里看到的,ngrx Entity DataService 有一个休息模式,所以它发送一个 put 像PUT api/heroes/1:但在 odata 模式中,您应该这样做:PUT api/heroes(1).

除此之外,我们在 OData 中还有使用 api 的函数和操作,例如: GET api/heroes/Default.GetMostPowerful(minimumPower=5).

此外,我们还有 Odata 的返回模式,它是一个包含数据的包装器,如下所示:

{
    "@odata.context": "http://localhost:57003/api/v2/$metadata#Users",
    "value": [
        {
            "id": 1,
            "mail": "foo@foo.com",
            "displayName": "foo, Adam "
        },
        {
            "id": 2,
            "mail": "bar@bar.com",
            "displayName": "bar, Andy",
        }
}

我怎样才能覆盖这一切?是否有任何服务可以扩展并提供给 Angular 以实现所有 odata 模式?

提前致谢!

- 编辑 -

感谢@Meligy,我可以执行 odata 持久性,但我仍在努力使用 odata 功能。这是我到目前为止所做的:

const getByEmail = createAction(
  '[User] Get User by Email',
  (payload: string) => ({ payload })
);

@Injectable({ providedIn: 'root' })
export class UserService extends EntityCollectionServiceBase<User> {
  constructor(serviceElementsFactory: EntityCollectionServiceElementsFactory) {
    super('User', serviceElementsFactory);
  }

  getByEmail(email: string) {
    this.dispatch(getByEmail(email));
  }
}

当你调用getByEmail('foo@foo.com')它时,它会调度动作,但我不知道如何扩展effects来调用我的扩展类,DefaultDataService然后使用获取的数据再次调度成功动作。

我已经DefaultDataService准备好扩展类中的函数来获取数据,但我正在尝试找到一种方法来从操作中触发它。

export class OdataService<T> extends DefaultDataService<T> {
  constructor(entityName: string, protected factory: OdataServiceFactory) {
    super(entityName, factory.http, factory.httpUrlGenerator);
  }

  protected buildRoute(id?: number) {
    const route = this.factory.pluralizzer.pluralize(this.entityName);

    return id
      ? `${environment.api}/${route}(${id})`
      : `${environment.api}/${route}`;
  }

  protected getCollection(route: string) {
    return this.http.get<any>(route).pipe(
      map(data => data.value)
    );
  }

  protected getOne(route: string) {
    return this.http.get<any>(route).pipe(
      map(data => {
        delete data['@odata.context'];
        return data;
      })
    );
  }

  protected serializeParams(params?: Dictionary<any>) {
    if (!params) {
      return '';
    }

    return Object.keys(params).map(key => `${key}=${params[key]}`).join(',');
  }

  getAll() {
    return this.getCollection(this.buildRoute());
  }

  getWithQuery(params: string) {
    return this.getCollection(`${this.buildRoute()}?${params}`);
  }

  getById(key: number) {
    return this.getOne(this.buildRoute(key));
  }

  // this is the function method that will call my generic odata functions
  // so the question is how to tell ngrx/data that my custom action should come here
  getFunction(namespace: string, name: string, params?: Dictionary<any>) {
    const route = this.buildRoute();
    const url = `${route}/${namespace || 'Default'}.${name}(${this.serializeParams(params)})`;

    return this.getOne(url);
  }
}
4

2 回答 2

2

您应该能够覆盖实体服务并定义您自己的 URL。

文档简要提及: https ://ngrx.io/guide/data#creating-entity-data-services

但是后来成为 NGRX Data 的库在旧仓库 https://github.com/johnpapa/angular-ngrx-data/blob/master/docs/entity-dataservice.md#custom-entitydataservice中有一个更清晰的示例

于 2020-01-16T22:43:19.947 回答
0

只是为了更新这个主题......在与 ngrx 苦苦挣扎之后,我发现了另一个比 ngrx 更好的框架,称为akita

它非常易于使用,而且样板文件少得多,因此很容易为其实现 OData 模式。我什至创建了这个库来和秋田一起工作,看看:

https://github.com/rosostolato/akita-ng-odata-service

于 2020-05-06T20:52:28.150 回答