[英]@NgModule static forRoot when implementing dynamic modules
我在@NgModule 中有這段代碼:
@NgModule({
declarations: [
AppComponent,
DashboardComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
ClarityModule,
RouterModule.forRoot([
{
path: '', redirectTo: 'dashboard', pathMatch: 'full'
},
{
path: 'dashboard', component: DashboardComponent
},
], {useHash: true}),
LibraryTestModule.forRoot(ServicetestService),
HttpModule
],
如果您可以看到我正在將 ServicetestService 注入 LibraryTestModule。
但在我的情況下,我使用下面的代碼使用 system.js 動態加載這個模塊:
// now, import the new module
return SystemJS.import(`${url}`).then((module) => {
console.log(module);
return SystemJS.import(`${url}`).then((module) => {
console.log(module);
return this.compiler.compileModuleAndAllComponentsAsync(module[`${moduleInfo.moduleName}`]).then(compiled => {
console.log(compiled);
return module;
});
});
});
現在有什么方法可以在動態加載模塊時將 ServiceTestService 注入到compileModuleAndAllComponentsAsync方法中?
經過一段時間的探索,我想我已經找到了解決方案。
export const DYNAMIC_CONFIG = new InjectionToken('DYNAMIC_CONFIG');
@NgModule({
imports: [
CommonModule,
],
declarations: [WidgetComponent],
entryComponents: [WidgetComponent]
providers: [
]
})
export class WidgetModule { }
現在讓我們假設您正在將此模塊動態加載到 shell 組件中:
ngOnInit () {
const parentInjector = Injector.create({
providers: [
{ provide: DYNAMIC_CONFIG, useValue: { message: 'CUSTOM VALUE PROVIDED BY THE CONSUME!' } }
],
parent: this.inj
});
import('./widget/widget.module.ts')
.then(m => {
this.compiler.compileModuleAndAllComponentsAsync(m.WidgetModule)
.then(moduleWithCompFactories => {
const module = moduleWithCompFactories.ngModuleFactory.create(parentInjector);
/**
* Adding the components from the lazy-loaded module
* into the current view
*/
this.vc.createComponent(moduleWithCompFactories.componentFactories[0], 0, parentInjector);
})
})
}
<ng-container #vc></ng-container>
如您所見,如果您的依賴項(由模塊的使用者提供)將用於作為該模塊一部分的組件並且您使用compileModuleAndAllComponentsAsync
方法,則組件將無法訪問該依賴項,除非手動創建另一個注入器。
這是因為,從方法的名稱可以看出,組件已經被編譯,所以除了在模塊中明確定義的那些之外,您不能動態添加其他依賴項。
如果模塊內的組件依賴於提供的依賴項,您可以通過首先編譯模塊( compileModuleAsync
)然后單獨編譯每個組件來實現(這聽起來可能很乏味,但我可以向您保證,您會喜歡使用它東西)。 這樣,他們將能夠在運行時注入任何動態提供的依賴項和事件。
@NgModule({
imports: [
CommonModule,
// RouterModule.forChild([{ path: '', component: WidgetComponent }])
],
declarations: [WidgetComponent],
// No need to use this when using `compileModuleAndAllComponentsAsync`
entryComponents: [WidgetComponent],
providers: [
{
provide: 'widgets',
useValue: [
{
name: 'widget1',
component: WidgetComponent,
},
],
}
]
})
export class WidgetModule { }
ngOnInit () {
const parentInjector = Injector.create({
providers: [
{ provide: DYNAMIC_CONFIG, useValue: { message: 'CUSTOM VALUE PROVIDED BY THE CONSUME!' } }
],
parent: this.inj
});
import('./widget/widget.module.ts')
.then(m => {
this.compiler.compileModuleAsync(m.WidgetModule)
.then(factory => {
const module = factory.create(parentInjector);
const [firstWidget] = module.injector.get('widgets');
const componentFactory = module.componentFactoryResolver.resolveComponentFactory(firstWidget.component);
this.vc.createComponent(componentFactory);
});
})
}
現在,每次您想向模塊添加另一個組件時,請確保將其添加到entryComponents
和組件數組,以便您可以使用module.injector.get()
檢索它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.