Ngx-bootstrap: fix(modal): modal does not properly work in a lazy loaded module

Created on 4 Aug 2017  路  25Comments  路  Source: valor-software/ngx-bootstrap

To have working modal in a lazy-loaded module you have to import modal module with forRoot() in that lazy module which is not correct as BsModalService will get a new instance and will not know anything about other modals of other modules (e.g. nesting won't properly work). If you skip the forRoot() you will get:

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

That's happening because ComponentLoaderFactory is provided only in root module which does not know anything about lazy-loaded injector and factories.

Proper fix would be to have some kind of overlay service that is provided with every ModalModule import.

Reproduction - https://stackblitz.com/edit/ngx-bootstrap-playground-mtwpzg

comp(modal) issue reproduce

Most helpful comment

@psined1 Just import ModalModule.forRoot() in your lazy-loaded module.

All 25 comments

Is there a workaround? I have exactly the same issue

Edit
I have a workaround. I will use the directive with some ViewChilds.

Running into the same issue. Could you share an example please?

@psined1 Just import ModalModule.forRoot() in your lazy-loaded module.

yep, did that, works fine

Also having the same issue. The workaround pointed by @dzonatan fixes it, but I don't know what are the implications of using forRoot in a child module.

Having same issue, is there an update?

I wouldn't reimport ModalModule.forRoot() as it will create a new BsModalService and then you'll have multiple of these services which are trying to manage some global UI state. It would work fine if you don't plan on using the service to call something like bsModalService.hide(1) from another context (which our app does to force close modals upon a navigation event).

I think the easiest solution would be (while still somewhat kludgy), for the lazy loaded module to provide its own ComponentLoaderFactory and extend ModalOptions to allow us to give our own ComponentLoaderFactory as then it would have the correct underlying ComponentFactoryResolver which could resolve lazy entryComponents (at least according to https://github.com/angular/angular/issues/14324).

advances?

Any updates on this?

Nov 2018, still broken?

https://github.com/valor-software/ngx-bootstrap/pull/3361 aims to fix it, but according to @valorkin it is still broken. Sadly, the modal roadmap issue https://github.com/valor-software/ngx-bootstrap/issues/3258 does not show progress for about a year, too 馃槩

Edit: You can use TemplateRefs in lazy loaded modules, but not Components

Any updates on this?

I needed to perform an action every time I opened a modal in a lazy module to be able to do this. I create a shared module and import the modal module and in the constructor add a listener to the event emiter that the BModalService has. In this way I was not forced to be repeating this in all the modules where I wanted to do this.

I hope you can help them this.

Same problem, after almost two years ;(
Check this reproduction, maybe it will help revive this thread.

As a side note, I've tried to apply workaround that @thetric proposed - yes, it works but only until you need BsModalRef service injected into your modal to programmatically manipulate/hide dialog. Another propose was to use <ng-template /> - this will produce a lot of duplicates if you need to reuse it somewhere.

Disappointed...

Any update on the issue?

I believe this is an Angular issue here. But wow, this issue still not closed.

This is not entirely an angular issue. The way how ng works is not compatible to your guys implementation. The lazy load module encapsulation will never allow provide lazy load factories on global FactoryResolver.

The way ng team and obter libs fixed this issue is working w/ two services. One provided in Module Scope, dedicated to resolve component reference. And a second service provided in root scope to handle multiple modal instances.

In short, the local service will resolve the component reference w/ local factory resolver, and then inject a global service to deal w/ multiple instances of resolved components/modals.

驴Any updates on this?

I'm getting multiple modalService instances because of the "ModalModule.forRoot()" workaround, and by doing this I can't use "setDismissReason" and the "onHide" event properly for all the modals.

Thanks for the great library.

Bringing this issue up again.

And again

Is this issue present in Angular 9? When I was updating from Angular 8.2 to Angular 9.1 it said following.

image

@jeserkin No, it's actually not an issue with Angular 9 :) I got rid of it after the upgrade.

So to conclude. Update to Angular 9 and entryComponent issue is resolved + https://github.com/valor-software/ngx-bootstrap/issues/2356#issuecomment-337816560

But it still generates multiple instances of modalService(one for each lazy loaded module) which is not correct.

Doesn't tooltip and popover do the same? They also require TooltipModule.forRoot(), PopoverModule.forRoot() as far as I know.

Was this page helpful?
0 / 5 - 0 ratings