Reputation: 222319
Considering that there is a module
@NgModule({
imports: [
Ng2Webstorage.forRoot({ prefix: 'SOME_PREFIX' }),
FooModule.forRoot(...),
BarModule,
],
exports: [
Ng2Webstorage,
FooModule,
BarModule,
]
})
class FeatureModule {
static forRoot(config): ModuleWithProviders {
return {
ngModule: FeatureModule,
providers: [...]
};
}
}
How can it pass prefix
to Ng2Webstorage.forRoot
dynamically? Like:
@NgModule({
imports: [
BarModule,
],
exports: [
Ng2Webstorage,
FooModule,
BarModule,
]
})
class FeatureModule {
static forRoot(config): ModuleWithProviders {
return {
ngModule: FeatureModule,
imports: [
Ng2Webstorage.forRoot({ prefix: config.name }),
FooModule.forRoot(config.foo)
],
providers: [...]
};
}
}
...
imports: [FeatureModule.forRoot({ name: `ANOTHER_PREFIX` }), ...]
...
Is it possible to have nested forRoot
calls?
It looks like ModuleWithProviders
doesn't accept imports
.
Upvotes: 3
Views: 1989
Reputation: 17723
It is possible by explicitly redefining the providers in forRoot()
. Other elements of the package can be imported and exported in the usual way.
Note that I use Array.concat() to easily chain multiple modules.
@NgModule({
imports: [
BarModule,
],
exports: [
Ng2Webstorage,
FooModule,
BarModule,
]
})
class FeatureModule {
static forRoot(config): ModuleWithProviders {
return {
ngModule: FeatureModule,
/* Explicitly redefine the providers from imported/exported modules. */
providers: [].concat(
Ng2Webstorage.forRoot({ prefix: config.name }).providers,
FooModule.forRoot(config.foo).providers
)
};
}
}
EDIT:
The above doesn't work when you use AOT compilation. Instead, use the following workaround with static exported function AND typed argument, e.g. config
.
export function ng2WebstorageProviders(name: string) {
return Ng2Webstorage.forRoot({ prefix: name }).providers;
}
export function fooProviders(foo: object) {
return FooModule.forRoot(foo).providers;
}
@NgModule({
imports: [
BarModule,
],
exports: [
Ng2Webstorage,
FooModule,
BarModule,
]
})
class FeatureModule {
static forRoot(config: {name: string, foo: object}): ModuleWithProviders {
return {
ngModule: FeatureModule,
/* Explicitly redefine the providers from imported/exported modules. */
providers: [
...ng2WebstorageProviders(config.name),
...fooProviders(config.foo)
]
};
}
}
For reference:
Upvotes: 2
Reputation: 214017
Yes, you're right. We can't pass imports
to ModuleWithProviders
import.
Here is how angular collects data from such import:
} else if (importedType && importedType.ngModule) {
const moduleWithProviders: ModuleWithProviders = importedType;
importedModuleType = moduleWithProviders.ngModule;
if (moduleWithProviders.providers) {
providers.push(...this._getProvidersMetadata(
moduleWithProviders.providers, entryComponents,
`provider for the NgModule '${stringifyType(importedModuleType)}'`, [],
importedType));
}
https://github.com/angular/angular/blob/4.3.x/packages/compiler/src/metadata_resolver.ts#L448-L456
We can override provider declated within Ng2Webstorage.forRoot() by passing the same provider within ModuleWithProviders.providers
like this:
import {Ng2Webstorage, WEBSTORAGE_CONFIG} from 'ngx-webstorage';
@NgModule({
imports: [
Ng2Webstorage.forRoot()
],
...
})
export class FeatureModule {
static forRoot(config): ModuleWithProviders {
return {
ngModule: FeatureModule,
providers: [
{ provide: WEBSTORAGE_CONFIG, useValue: config }
]
};
}
}
Upvotes: 4