动态创建其他模块的组件

时间:2017-03-21 13:44:20

标签: javascript angular typescript angular2-services

我需要一个全局模态开启服务,可以从任何模块创建动态组件。 我有多个模块,每个模块都有模态组件。我简化了我的项目结构:

AppModule  
     ---ModalOpenerService
        --ModalTemplate
     ---AModule
            ---ModalComponent1
            ---ModalComponent2
            ---SimpleComponent
     ---BModule
            ---ModalComponent3
            ---ModalComponent4

模态开启者服务有这样的方法:

@ViewChild('modalContainer', {read: ViewContainerRef}) modalContainer;

showModal(component: Type<any>,data?:any){
    let componentFactory = this.resolver.resolveComponentFactory(component);
    this.modalContainer.createComponent(componentFactory );
}

我希望我的ModalOpenerService能够创建任何模态组件并显示它。但问题是模态组件属于不同的模块,模态开启器无法在其注入器的组件工厂列表中找到它们。

No component factory found for ModalComponent1. Did you add it to @NgModule.entryComponents

显然,ModalComponent1不是AppModule的成员。

我可以通过将工厂方法作为参数而不是像这样的组件类型传递来打开模态

 //In SimpleComponent, I call my ModalOpenerService to open modal1. Because
 //the simpleComponent's parent injector (AModule's injector) can find Modal1,
 //this.resolver can resolve Modal1.
showModal1(){
   this.modalOpenerService.showModal(this.resolver.resolveComponentFactory(ModalComponent1));
}

在ModalOpenerService

@ViewChild('modalContainer', {read: ViewContainerRef}) modalContainer;

showModal(factory:ComponentFactory<any>, data?:any){
    this.modalContainer.createComponent(factory);
}

因此,模块创建自己的组件,并且能够在entryComponents数组中找到组件。

我们还有一个问题,因为在AppModule范围内创建的任何模态组件,如果我想从模态显示另一个模态,AppModule的注射器仍然无法找到它。

一种解决方案可以是将所有模态放入ModalOpenerService的同一模块中,但我希望所有模态都在自己的模块中。

任何结构设计建议也欢迎

1 个答案:

答案 0 :(得分:0)

您需要将ModalOpenerService作为单独的模块

    export class ModelModule {
    static WithComponents(components: Array<Type<any>>): Array<any> {
        return {
            ngModule: ModelModule,
            providers: [
                { provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: components, multi: true }
            ]
        }
    }
}

从AModule和BModule你可以包含一个ModelModule,如下所示

    @NgModule({
    imports: [BrowserModule, ModelModule.WithComponents([ModalComponent1, ModalComponent2])],
    declarations: [AppComponent, ModalComponent1, ModalComponent2],
    bootstrap: [AppComponent],
    providers: []
})
export class AModule { }