You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
MatDialog: When using in dynamically loaded component throws error No provider for MatDialog #19335
Add MatDialogModule to the imports array of NGModule for the dynamically loaded component.
ng serve and check the error in console.
Expected Behavior
It should work without throwing any error.
Actual Behavior
Throws below error:
zone-evergreen.js:659 Unhandled Promise rejection: R3InjectorError(AppBrowserModule)[MatDialog -> MatDialog -> MatDialog]:
NullInjectorError: No provider for MatDialog! ; Zone: <root> ; Task: Promise.then ; Value: NullInjectorError: R3InjectorError(AppBrowserModule)[MatDialog -> MatDialog -> MatDialog]:
NullInjectorError: No provider for MatDialog!
at NullInjector.get (http://localhost:4200/vendor.js:34269:27)
at R3Injector.get (http://localhost:4200/vendor.js:48199:33)
at R3Injector.get (http://localhost:4200/vendor.js:48199:33)
at R3Injector.get (http://localhost:4200/vendor.js:48199:33)
at NgModuleRef$1.get (http://localhost:4200/vendor.js:65751:33)
at Object.get (http://localhost:4200/vendor.js:63486:35)
at getOrCreateInjectable (http://localhost:4200/vendor.js:38115:39)
at Module.ɵɵdirectiveInject (http://localhost:4200/vendor.js:52134:12)
at NodeInjectorFactory.MyDynamicallyLoadedComponent_Factory [as factory]
Environment
Angular: 10.0.0-next.6 (same behavior in other versions e.g. 9.x)
CDK/Material: 9.2.3
Browser(s): Chrome
Operating System (e.g. Windows, macOS, Ubuntu): Windows
Thank you, I have added you to a private repo, just run ng serve and you will notice the error in the console. In AppComponent, I'm trying to dynamically load the EnableNotificationsComponent. Although the component file contains
@naveedahmed1 can you try what @devversion mentioned in #19616? The main thing is to ensure that you're using the MatDialog instance (to call dialog.open) that's provided/imported from the same NgModule in which the lazy-loaded component is declared.
If you take a look at my comment here #19335 (comment) I am doing exactly the same, but the only difference is I am loading this component dynamically and not through router.
@naveedahmed1 I think the issue here is that you use the ComponentFactoryResolver from the root module and directly create the lazy component. It never goes through the lazy app module though, so the MatDialogModule with its's root providers (i.e. MatDialog service) are not having any effect.
The right solution would be to either:
Add the MatDialogModule to the root module so that the service is available in your whole application
Retrieve the ComponentFactoryResolver for the lazy module and instantiate the component through that.
If you go with (2), you might want to use Compiler#compileModuleSync, or directly work with NgModuleFactory. If the module is compiled with ngtsc, then the actual class is considered a factory in Ivy and you could wrap it in a NgModuleFactory, create an instance of it and then bootstrap a component with it. We have an internal example here (using Ivy factory shims though):
The code responsible for loading the actual module with it's providers is the following. Disclaimer: Can still be optimized with parallel loading but here it's sufficient for the example:
Activity
naveedahmed1 commentedon May 16, 2020
To reproduce the error, lazy load below component in
AppModuleLazy import the above component in
AppModule:jelbourn commentedon May 29, 2020
@naveedahmed1 any chance you could make a reproduction GitHub repo?
naveedahmed1 commentedon May 29, 2020
Thanks @jelbourn , can I add you to a private repo?
jelbourn commentedon May 30, 2020
Sure
naveedahmed1 commentedon May 30, 2020
Thank you, I have added you to a private repo, just run
ng serveand you will notice the error in the console. InAppComponent, I'm trying to dynamically load theEnableNotificationsComponent. Although the component file containsits still throwing error
Unhandled Promise rejection: R3InjectorError(AppBrowserModule)[MatDialog -> MatDialog -> MatDialog]: NullInjectorError: No provider for MatDialog! ; Zone: <root> ; Task: Promise.then ; Value: NullInjectorError: R3InjectorError(AppBrowserModule)[MatDialog -> MatDialog -> MatDialog]: NullInjectorError: No provider for MatDialog!faradoxuz commentedon Jun 17, 2020
Same problem
jelbourn commentedon Jun 18, 2020
I went to look today, but the invitation expired. The code you linked does look like it should work, though.
naveedahmed1 commentedon Jun 18, 2020
I added you again, can you please try it now?
jelbourn commentedon Jun 23, 2020
@naveedahmed1 I still get a 404 from the invite
naveedahmed1 commentedon Jun 23, 2020
That's strange, I just removed you from collaborators and added again
jelbourn commentedon Jun 24, 2020
Seems to have worked that time; I'll try to take a peek tomorrow during my weekly scheduled triage time
naveedahmed1 commentedon Jun 24, 2020
Thank you so much @jelbourn :)
tc4rdpp commentedon Jul 30, 2020
Hello, any news on this?
I am having a similar issue.
Thanks.
crisbeto commentedon Aug 9, 2020
I believe this is the same issue as #19616. You can check it out for a better explanation.
jelbourn commentedon Aug 13, 2020
@naveedahmed1 can you try what @devversion mentioned in #19616? The main thing is to ensure that you're using the
MatDialoginstance (to calldialog.open) that's provided/imported from the same NgModule in which the lazy-loaded component is declared.naveedahmed1 commentedon Aug 13, 2020
@jelbourn thank you for your response.
If you take a look at my comment here #19335 (comment) I am doing exactly the same, but the only difference is I am loading this component dynamically and not through router.
devversion commentedon Aug 24, 2020
@naveedahmed1 I think the issue here is that you use the
ComponentFactoryResolverfrom the root module and directly create the lazy component. It never goes through the lazy app module though, so theMatDialogModulewith its's root providers (i.e.MatDialogservice) are not having any effect.The right solution would be to either:
MatDialogModuleto the root module so that the service is available in your whole applicationComponentFactoryResolverfor the lazy module and instantiate the component through that.If you go with (2), you might want to use
Compiler#compileModuleSync, or directly work withNgModuleFactory. If the module is compiled with ngtsc, then the actual class is considered a factory in Ivy and you could wrap it in aNgModuleFactory, create an instance of it and then bootstrap a component with it. We have an internal example here (using Ivy factory shims though):components/src/components-examples/private/load-example.ts
Lines 14 to 17 in f0c7a25
More general best-practices are probably in the Angular docs or in various great blog posts.
devversion commentedon Aug 24, 2020
I've created a StackBlitz that shows the issue: https://stackblitz.com/edit/19335-before?file=src/main.ts. Here is an example with fix as per (2): https://stackblitz.com/edit/19335-with-fix?file=src/main.ts
The code responsible for loading the actual module with it's providers is the following. Disclaimer: Can still be optimized with parallel loading but here it's sufficient for the example:
Closing as this seems to work as expected. Please let us know if this does not work. An issue with an updated StackBlitz would be great. Thanks!
angular-automatic-lock-bot commentedon Sep 26, 2020
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.