Unable to open lazy loaded modal’s component from app wide singleton service

Bug description:

I am trying to create a single entry point for handling all modal’s related logic following DRY (don’t repeat yourself) principle, which would help in improving modal handling through out our application, (which actually heavily relies on modals)

So instead of replicating modal handling logic inside each component (which was happening before), I have moved modal handling logic to a separate service (singleton throughout the app) provided in the main app module. This is what that service modal handling method looks like, (I have omitted some irrelevant configurations)

  openModal(content: any, size?: 'sm' | 'lg' | 'xl', windowClass: string = 'compact') {
    if (size === 'xl') {
      size = 'xl' as 'lg';
    }
    const ngbModalOptions: NgbModalOptions = {
      backdrop: 'static',
      keyboard: true,
      size: size
    };
    if (windowClass) {
      ngbModalOptions.windowClass = windowClass;
    }

    return this.ngbModal.open(content, ngbModalOptions);
  }

and this is how I am triggering it,

this.modalService.openModal(LazyModalComponent);

Just to make it clear, my lazy loaded modules / (shared module in my actual application) does import +export NgbModule, and I have also added my modal content component to entryComponents,

@NgModule({
  imports: [
    CommonModule,
    RouterModule.forChild(routes),
    NgbModalModule
  ],
  declarations: [LazyComponent, LazyModalComponent],
  entryComponents: [LazyModalComponent]
})

when I try to open any modal from lazy loaded modules I am getting following error,

Error: No component factory found for LazyModalComponent. Did you add it to @NgModule.entryComponents?

If I call a local version of the same method from inside lazy loaded module, modal opens fine, this only happens when I try to use modals using a wrapper app wide singleton service.

P.S I did explored some closed issues regarding the subject but almost all of those are related to not importing NgbModule in their lazy loaded module which is not the case here.

Link to minimally-working StackBlitz that reproduces the issue:

https://stackblitz.com/edit/angular-kzh4wr

Versions of Angular, ng-bootstrap and Bootstrap:

Angular: 7.1.2

ng-bootstrap: 4.0.0

Bootstrap: 4.1.3

2 thoughts on “Unable to open lazy loaded modal’s component from app wide singleton service

  1. but is there any other possible solution keeping my service singleton?
    I don’t want creating separate instance of modalService for each lazy loaded module.

    There is no other option in the current Angular. One again, in the current Angular entry components are scoped to a lazy loaded module and top-level module can’t see entry components from lazy-loaded modules.

    Things will change for better in the ivy version in Angular (on which I’m actively working so this info is first-hand). Till then what I’ve shoved in in the stackblitz is the best you can do.