问题
I need to send a configuration (array of objects) to a service in a feature module and this configuration needs to be dynamically calculated. I used forRoot
and it worked fine until I've built it with --aot
.
problem: With --aot
, the configuration results in undefined
.
Here is a link to an example I made on stackblitz: https://stackblitz.com/edit/angular-aot-forroot-error
!! it works as desired on stackblitz, since it is not built with aot !! If you build it locally with aot, though, the GetConfigService
will throw an error since config
will be undefined.
Important parts:
AppModule:
export const config = [
{
id: 'first'
},
{
id: 'second'
}
];
// just illustrative modification (in my project I need to modify config based on environment)
export function modifyConfig(config) {
return config.map(c => c.id === 'first' ? {...c, default: true} : c);
}
const configModified = modifyConfig(config);
@NgModule({
imports: [
BrowserModule,
WithParametersdModule.forRoot(configModified)
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
WithParametersdModule:
@NgModule()
export class WithParametersdModule {
static forRoot(config) {
return {
ngModule: WithParametersdModule,
providers: [
{
provide: SOME_CONFIG,
useValue: config
},
GetConfigService
]
}
}
}
GetConfigService:
@Injectable()
export class GetConfigService {
constructor(@Inject(SOME_CONFIG) private config) {}
get configObj() {
if (!this.config) {
throw `config: ${this.config}`;
}
return this.config;
}
}
Thanks for help or explanation of what am I doing wrong.
回答1:
I found that it might be because AOT would try to replace useValue
at compile time but when you pass these values at runtime so AOT just replace it with undefined
. The solution is use useFactory
instead of useValue
. This solved this problem.
Here is what I did:
// Declare a function type which returns the config
export type ConfigFunction = () => any;
// Replace useValue with useFactory
@NgModule()
export class WithParametersdModule {
static forRoot(config: {
func: ConfigFunction,
// You could add other config parameters here...
}) {
return {
ngModule: WithParametersdModule,
providers: [
{
provide: SOME_CONFIG,
useFactory: config.func
},
GetConfigService
]
}
}
}
Then you can use it as following:
export function getConfig(): any {
return {
id: 'first'
},
{
id: 'second'
};
}
@NgModule({
// ...
imports: [
BrowserModule,
WithParametersdModule.forRoot({ func: getConfig }),
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
来源:https://stackoverflow.com/questions/50131083/angular-aot-build-dynamic-forroot-parameter-results-in-undefined