@ngrx/data с внутренним сервером odata
Я уже привык к 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);
}
}
2 ответа
Вы должны иметь возможность переопределить Entity Service и определить свой собственный URL.
В документах это кратко упоминается:https://ngrx.io/guide/data
Но библиотека, которая позже стала NGRX Data, имеет более четкий пример в старом репо https://github.com/johnpapa/angular-ngrx-data/blob/master/docs/entity-dataservice.md
Просто чтобы обновить эту тему... после борьбы много с ngrx, я нашел другую основу, которая намного лучше, то ngrx называется акита.
Он настолько прост в использовании и гораздо менее шаблонен, что легко реализовать для него шаблон OData. Я даже создал эту библиотеку для работы с akita, посмотрите: