After reviewing the docs specifically:
Custom EntityDataService and
Replace the HttpUrlGenerator
I came up with this solution. Anyone feel free to comment.
- Define/review your data types - entity metadata - entity names;
- Create mapping to plurals for non-default plural entity names (default is: name + 's');
- For entities with the non-default root URL create a mapping of entity names to specific URL;
File: ../entity-metadata.ts
// Step 1:
const entityMetadata: EntityMetadataMap = {
Hero: {},
Villan: {},
Creature: {},
DataA01: {}
// etc.
}
// Step 2:
const pluralNames = {
Hero: 'heroes',
DataA01: 'data-a01'
}
export const entityConfig = {
entityMetadata,
pluralNames
};
// Step 3:
export const rootUrls = {
// Hero: - not needed here, data comes from default root
Villan: 'http://localhost:4001',
Creature: 'http://localhost:4001',
DataA01: 'http://remoteserver.net:80/publicdata',
}
- Replace the HttpUrlGenerator (doc) with your own URL generator (DynamicHttpUrlGenerator)
File: ../http-dyn-url-generator.ts
import { Injectable } from '@angular/core';
import {
DefaultHttpUrlGenerator,
HttpResourceUrls,
normalizeRoot,
Pluralizer,
DefaultPluralizer,
} from '@ngrx/data';
import { rootUrls } from '../data/ngrx-data/db01-entity-metadata';
@Injectable()
export class DynamicHttpUrlGenerator extends DefaultHttpUrlGenerator {
constructor(private aPluralizer: Pluralizer = new DefaultPluralizer(undefined)) {
super(aPluralizer);
}
protected getResourceUrls(entityName: string, root: string): HttpResourceUrls {
let resourceUrls = this.knownHttpResourceUrls[entityName];
if ( ! resourceUrls) {
// rootUrls contains
// mapping of individual ngrx data entities
// to the root URLs of their respective data sources.
// It contains only entities which do not have
// the default root URL.
if (rootUrls.hasOwnProperty(entityName)) {
root = rootUrls[entityName];
}
const nRoot = normalizeRoot(root);
const url = `${nRoot}/${this.aPluralizer.pluralize(entityName)}/`.toLowerCase();
// remove after testing
console.log('-- entityName: ' + entityName + ', URL: ' + url)
resourceUrls = {
entityResourceUrl: url,
collectionResourceUrl: url
};
this.registerHttpResourceUrls({ [entityName]: resourceUrls });
}
return resourceUrls;
}
}
For each of your data entity create a custom EntityDataService
- HeroDataService
- VillanDataService
- CreatureDataService
- DataA01DataService
- etc.
(doc and code is here) - the code example is under
// store/entity/hero-data-service.ts
- Register your DynamicHttpUrlGenerator and your custom EntityDataServices in your app's module, in my case:
File: ../ngrx-data-store.module.ts
(in a simple app, directly in file: app.module.ts)
@NgModule({
imports: [ ... ],
providers: [ { provide: HttpUrlGenerator, useClass: DynamicHttpUrlGenerator },
HeroDataService,
VillanDataService,
CreatureDataService,
DataA01DataService
]
})
Use your custom EntityDataServices in your components for each given entity the same way as all standard or default EntityDataServices to fetch data. The data will be pulled from the respective URLs you set in the const: rootUrls.
Don't forget to get your URLs' data server(s) configured and started.
A few important considerations:
- on your server you may need to enable CORS handling. E.g: on nestjs use:
app.enableCors();
- if your client app uses: Angular in-memory-web-api you need to enable access to remote server as follows:
File: ../in-mem-data.module.ts (or as you named it)
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemDataService } from '../../services/data/in-mem-data/in-mem-data.service';
@NgModule({
imports: [
HttpClientModule,
HttpClientInMemoryWebApiModule.forRoot(InMemDataService, {
passThruUnknownUrl: true // <--- IMPORTANT for remote data access
}),
]
})
export class InMemDataModule {}