components
components copied to clipboard
bug(Dialog): Explicit injector does not work
Is this a regression?
- [ ] Yes, this behavior used to work in the previous version
The previous version in which this bug was not present was
No response
Description
Hey, I recently updated to v14 just for the newly added feature of the Dialog - the explicit injector, but it does not seem to work. I might be doing something wrong or misunderstood the new feature (to provide an Injector
without having to provide a ViewContainerRef
).
Reproduction
Steps to reproduce: Check out https://stackblitz.com/edit/angular-ozdqwy?file=src%2Fapp%2Fdialog-overview-example.ts (hope this lives long enough) OR
- Open the dialog example https://stackblitz.com/run?file=src/app/dialog-overview-example.ts
- Add some service
@Injectable() export class SomeService { test = 123; }
- Create an injector
const myInjector = Injector.create({ providers: [{ provide: SomeService }] });
- Pass the injector
injector: myInjector`` to ``this.dialog.open
- Require the service
public someService: SomeService
inDialogOverviewExampleDialog
's constructor
Expected Behavior
SomeService
gets provided to DialogOverviewExampleDialog
Actual Behavior
ERROR NullInjectorError: R3InjectorError(AppModule)[SomeService -> SomeService -> SomeService]:
NullInjectorError: No provider for SomeService!
at NullInjector.get (vendor.js:66456:21)
at R3Injector.get (vendor.js:66652:27)
at R3Injector.get (vendor.js:66652:27)
at R3Injector.get (vendor.js:66652:27)
at NgModuleRef.get (vendor.js:81766:29)
at ChainedInjector.get (vendor.js:81534:32)
at lookupTokenUsingModuleInjector (vendor.js:59680:31)
at getOrCreateInjectable (vendor.js:59732:10)
at Module.ɵɵdirectiveInject (vendor.js:67961:10)
at NodeInjectorFactory.DialogOverviewExampleDialog_Factory [as factory] (main.js:153:195)
Environment
Angular CLI: 14.0.5
Angular: 14.0.5
Angular Material: 14.0.4
Node: 16.13.0
Package Manager: npm 8.1.0
OS: win32 x64
Additional info
I glanced into the source code and I think the injector from the config is taken into account only when creating/attaching the container: https://github.com/angular/components/blob/c28bbdeb51c31cbd1f5e06528ef4d21b1650e4a8/src/cdk/dialog/dialog.ts#L224 but not when creating/attaching the actual content component: https://github.com/angular/components/blob/c28bbdeb51c31cbd1f5e06528ef4d21b1650e4a8/src/cdk/dialog/dialog.ts#L311 and it seems that from a DI point of view, the implementation does not tie the content's Injector with the container's Injector. Again, I might be wrong.
Thanks!
I have experienced the same, I've ended up needing to build components that (in a minor way) duplicate logic in order to specify providers instead of being able to pass up an injector.
I have the same issue, the MatDialog
implementation seems to work fine though, but the CDK dialog is unable to resolve the custom dependencies.
Hey @mpo-dev , that is wierd. The example I posted in the Reproduction section uses the MatDialog
. AFAIR MatDialog
is just a thin wrapper around the cdk's Dialog
and this issue should concern both of them.
@adzhiljano In my production code I had the situation where opening a custom component in a dialog with MatDialog
would work fine, but opening the same component in a dialog with Dialog
would result in one of the custom components dependencies not being resolvable. I need the CDK Dialog
because of the custom dialog container.
Hello! Have the same issue on our project with MatDialog. Can not divide application to modules, viewContainerRef doesn't work as well. Services, that are injected only to the lazy-loaded module can not be accessible from the Dialog.
It seems I found the root cause of the problem.
Component is created with deprecated API.
So, it used the deprecated version of createComponent
method with componentFactoryResolver.
https://github.com/angular/components/blob/main/src/cdk/portal/portal-directives.ts#L155
As a result, component is created with componentFactoryResolver
connected to the AppModule if it's not explicitly provided.
Is it possible to fix the issue?
I am also receiving this error using MatDialog on Angular 15.2.5
We are experiencing the same issue. Instead of providing only injector we are forced to provide also deprecated component factory resolver to instantiate it in the correct dependency injection context
this.matDialog.open(DialogComp, {
injector: this.cmpInjector,
componentFactoryResolver: this.cmpInjector.get(ComponentFactoryResolver),
})
@VeselyT's solution worked for me. I am trying to utilize a service to handle dialogs. Passing the "viewContainerRef" argument wasn't working, but once I used the componentFactoryResolver like VesleyT, it worked. The viewContainerRef option (or the injector option), are not passing the dependencies properly, as noted by others on this issue.
Having the same issue. I think the problem is in the ComponentPortal. I'm generating the dialog myself using portals and I'm experiencing the exact same behavior described by others.
Angular Version 17.2.3