使用 ngrx-data 如何配置应用程序以从特定 url 获取特定实体的数据
Using ngrx-data how to configure the app to fetch data of specific entities from specific urls
如果我们遵循 ngrx-data 示例并查看 Entity DataService,我们可以在没有任何配置的情况下获取内存中(硬编码)的英雄数据。默认值与我们配置的一样:
const defaultDataServiceConfig: DefaultDataServiceConfig = {
root: 'api', // or a running server url, e.g: 'http://localhost:4000/api'
timeout: 3000, // request timeout
}
例如:EntityStoreModule
@NgModule({
providers: [{ provide: DefaultDataServiceConfig, useValue: defaultDataServiceConfig }]
})
问题:
我们将如何配置我们的应用程序以从默认来源获取实体 "Heros" 的数据:
root: 'api'
实体 "Villans" 的数据来自 URL:
root: 'http://localhost:4000/villans'
以及其他实体的数据来自其 (other/various) 各自的 URLs ...?
具体查看文档后:
Custom EntityDataService 和
Replace the HttpUrlGenerator
我想出了这个解决方案。任何人都可以随意发表评论。
- Define/review你的数据类型-实体元数据-实体名称;
- 为非默认复数实体名称创建到复数的映射(默认为:名称 + 's');
- 对于具有非默认根 URL 的实体,创建实体名称到特定 URL;
的映射
文件:../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',
}
- 将 HttpUrlGenerator (doc) 替换为您自己的 URL 生成器 (DynamicHttpUrlGenerator)
文件:../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;
}
}
为您的每个数据实体创建一个自定义 EntityDataService
- 英雄数据服务
- 维兰数据服务
- 生物数据服务
- DataA01DataService
- 等等
(doc and code is here) - 代码示例在
下
// store/entity/hero-data-service.ts
- 在您的应用程序模块中注册您的 DynamicHttpUrlGenerator 和您的自定义 EntityDataServices,在我的例子中:
文件:../ngrx-data-store.module.ts
(在一个简单的应用程序中,直接在文件中:app.module.ts)
@NgModule({
imports: [ ... ],
providers: [ { provide: HttpUrlGenerator, useClass: DynamicHttpUrlGenerator },
HeroDataService,
VillanDataService,
CreatureDataService,
DataA01DataService
]
})
在每个给定实体的组件中使用您的自定义 EntityDataServices,使用与所有标准或默认 EntityDataServices 相同的方式来获取数据。数据将从您在 const 中设置的相应 URLs 中提取:rootUrls。
不要忘记配置并启动您 URL 的数据服务器。
几个重要的注意事项:
- 在您的服务器上,您可能需要启用 CORS 处理。例如:在 nestjs 上使用:
app.enableCors();
- 如果您的客户端应用程序使用:Angular in-memory-web-api 您需要启用对远程服务器的访问,如下所示:
文件:../in-mem-data.module.ts(或您命名的)
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 {}
如果我们遵循 ngrx-data 示例并查看 Entity DataService,我们可以在没有任何配置的情况下获取内存中(硬编码)的英雄数据。默认值与我们配置的一样:
const defaultDataServiceConfig: DefaultDataServiceConfig = {
root: 'api', // or a running server url, e.g: 'http://localhost:4000/api'
timeout: 3000, // request timeout
}
例如:EntityStoreModule
@NgModule({
providers: [{ provide: DefaultDataServiceConfig, useValue: defaultDataServiceConfig }]
})
问题:
我们将如何配置我们的应用程序以从默认来源获取实体 "Heros" 的数据:
root: 'api'
实体 "Villans" 的数据来自 URL:
root: 'http://localhost:4000/villans'
以及其他实体的数据来自其 (other/various) 各自的 URLs ...?
具体查看文档后: Custom EntityDataService 和 Replace the HttpUrlGenerator 我想出了这个解决方案。任何人都可以随意发表评论。
- Define/review你的数据类型-实体元数据-实体名称;
- 为非默认复数实体名称创建到复数的映射(默认为:名称 + 's');
- 对于具有非默认根 URL 的实体,创建实体名称到特定 URL; 的映射
文件:../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',
}
- 将 HttpUrlGenerator (doc) 替换为您自己的 URL 生成器 (DynamicHttpUrlGenerator)
文件:../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;
}
}
为您的每个数据实体创建一个自定义 EntityDataService
- 英雄数据服务
- 维兰数据服务
- 生物数据服务
- DataA01DataService
- 等等
(doc and code is here) - 代码示例在
下// store/entity/hero-data-service.ts
- 在您的应用程序模块中注册您的 DynamicHttpUrlGenerator 和您的自定义 EntityDataServices,在我的例子中:
文件:../ngrx-data-store.module.ts
(在一个简单的应用程序中,直接在文件中:app.module.ts)
@NgModule({
imports: [ ... ],
providers: [ { provide: HttpUrlGenerator, useClass: DynamicHttpUrlGenerator },
HeroDataService,
VillanDataService,
CreatureDataService,
DataA01DataService
]
})
在每个给定实体的组件中使用您的自定义 EntityDataServices,使用与所有标准或默认 EntityDataServices 相同的方式来获取数据。数据将从您在 const 中设置的相应 URLs 中提取:rootUrls。 不要忘记配置并启动您 URL 的数据服务器。
几个重要的注意事项:
- 在您的服务器上,您可能需要启用 CORS 处理。例如:在 nestjs 上使用:
app.enableCors();
- 如果您的客户端应用程序使用:Angular in-memory-web-api 您需要启用对远程服务器的访问,如下所示:
文件:../in-mem-data.module.ts(或您命名的)
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 {}