Dynamically create components of other modules

I need a global modal service that can create dynamic components from any module. I have several modules and each one has modal components. I have simplified my project structure as follows:

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

      

The modal opening service has a method like this:

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

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

      

I want my ModalOpenerService to be able to create any modal component and show it. But the problem is that modal components belong to different modules, and modal knife cannot find them in its injector factory component list.

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

      

Obviously ModalComponent1 is not a member of AppModule.

I could expose modals by passing a factory method as a parameter instead of the component type, like so:

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

      

In ModalOpenerService

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

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

      

This way, modules create their own components and they can find the component in their array entryComponents

.

We still have a problem because any modal created in the area AppModule

, and if I want to show another modal from the modal, the injector AppModule

still won't be able to find it.

One solution might be to include all modals in the same module using ModalOpenerService

, but I want all modals to be in its own module.

Any design design suggestions are also welcome

+3


source to share


1 answer


You must have ModalOpenerService as a separate module like

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

      



And from AModule and BModule you can include ModelModule like below

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

      

0


source







All Articles