13
votes

I am having issues with loading a component from a lazy loaded module, using Angular 6.

I created a library using the CLI - ng generate library @org/chat

Updated angular.json file to include:

"lazyModules": [
   "dist/org/chat"
],

and then loading the module successfully via AppComponent:

constructor(private _injector: Injector, private loader: SystemJsNgModuleLoader, public dialog: MatDialog) {}

load() {
   this.loader.load('dist/org/chat#ChatModule').then(moduleFactory => {
    const moduleRef = moduleFactory.create(this._injector);
   });
}

So far so good and the module is being loaded.

However, the ChatModule has a component called ChatPopupComponent and I can't find a way to show it using a dialog (or by adding it to a ViewChild container).

In order to open a component in a dialog it needs to be declared under the module's entryComponents plus imported at the AppComponent level:

 let dialogRef = this.dialog.open(ChatPopupComponent
     data: {}
  });

But when importing the component directly (and exporting it from the library) I get the following (obvious) error: 'Component ChatPopupComponent is not part of any NgModule or the module has not been imported into your module'. Since it is a lazy loaded module, it is clearly not imported yet.

When I try the following:

   let name: any = 'ChatPopupComponent';
   let dialogRef = this.dialog.open(name
         data: {}
      });

I get the following error - error loading module Error: No component factory found for EmailPopUpComponent. Did you add it to @NgModule.entryComponents?

It seems that the only way to show a component is by importing the module within the app.module.ts, although it defies the goal of having a lazy loaded module.

Is there a way to do the above or am I missing something rudimental about lazy loading modules & components?

3
Have you added this component in the exports of your org/chat NgModule?eduPeeth

3 Answers

1
votes

try to declare the ChatPopupComponent as a separate module..

chat-popup.component.ts

@NgModule({
    imports: [
        CommonModule,
        ...
    ],
    declarations: [ChatPopupComponent],
    exports: [ChatPopupComponent],
})
export class ChatPopupModule { }

..do the same for the EmailPopupComponent..

email-popup.component.ts

@NgModule({
    imports: [
        CommonModule,
        ...
    ],
    declarations: [EmailPopupComponent],
    exports: [EmailPopupComponent],
})
export class EmailPopupModule { }

..and add both modules to the ChatModule imports as well as the entryComponents array..

chat.module.ts

@NgModule({
    imports: [
        CommonModule,
        ...
        ChatPopupModule,
        EmailPopupModule,
    ],
    declarations: [
        ...
    ],
    entryComponents: [
        ChatPopupComponent,
        EmailPopupComponent,
    ]
})
export class ChatModule { }
0
votes

You can refer the following links which helped me

Angular site lazy loading

How to Implement

I've got the same problem, but in angular 6 it seems that every module loaded with "lazy loaded" has to be removed from the imports declaration in the root module (app.module.ts). At least for me that works.

Stack answer

0
votes

The component from which you are trying to load your EmailPopupComponent must know it. That means that the module where your component is declared needs to somehow have a reference to your EmailPopupComponent. This can be done in the two following ways:

  • declare the EmailPopupComponent in the same module as the component wanting to access it
  • import the module where the EmailPopupComponent is declared and exported (important that it is visible for other modules) in the module(s) where your component wanting to access it is declared. This should e.g. be done in a SharedModule containing components spread over the application.

Additionally to importing modules, there are is a so called entryComponents array available in the modules decorator. That one must, additionally to the reference in tha module, contain the EmailPopupComponent when you are using it in a dialog like a Material dialog (as you did in your example).