If we follow ngrx-data example and look at the Entity DataService, we can fetch the Hero data that we have in-memory (hard-coded) without any configuration. The default will work the same as if we configured:
const defaultDataServiceConfig: DefaultDataServiceConfig = {
root: 'api', // or a running server url, e.g: 'http://localhost:4000/api'
timeout: 3000, // request timeout
}
and in e.g: EntityStoreModule
@NgModule({
providers: [{ provide: DefaultDataServiceConfig, useValue: defaultDataServiceConfig }]
})
Question:
How will we configure our app to fetch data for entity "Heros" from the default source:
root: 'api'
and data for entity "Villans" from a URL:
root: 'http://localhost:4000/villans'
and data for other entities from their (other/various) respective URLs ...?
After reviewing the docs specifically: Custom EntityDataService and Replace the HttpUrlGenerator I came up with this solution. Anyone feel free to comment.
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',
}
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
(doc and code is here) - the code example is under
// store/entity/hero-data-service.ts
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:
app.enableCors();
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 {}