Reputation: 1872
I can't inject MatDialogRef as it described in documentation: https://material.angular.io/components/dialog/overview
When i'm trying to do it i'v got error:
ERROR Error: StaticInjectorError[MatDialogRef]: StaticInjectorError[MatDialogRef]: NullInjectorError: No provider for MatDialogRef!
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import {
MatInputModule,
MatDialogModule,
MatProgressSpinnerModule,
MatButtonModule,
MatDialog,
MatDialogRef
} from '@angular/material';
import { ApiModule } from '../api/api.module';
import { RoutingModule } from '../routing/routing.module';
import { RegistrationComponent } from './components/registration.component';
import { LoginComponent } from './components/login.component';
import { AccountService } from './services/account.service';
@NgModule({
imports: [
BrowserModule,
MatInputModule,
MatDialogModule,
MatProgressSpinnerModule,
MatButtonModule,
FormsModule,
RoutingModule,
ApiModule
],
declarations: [
RegistrationComponent,
LoginComponent
],
entryComponents: [
LoginComponent,
RegistrationComponent
],
providers: [
AccountService,
MatDialog,
MatDialogRef
]
})
export class AccountModule {}
home.component.ts
import { Component } from '@angular/core';
import { MatDialog } from '@angular/material';
import { RegistrationComponent } from '../account/components/registration.component';
@Component({
moduleId: module.id.replace('compiled', 'app'),
templateUrl: 'home.component.html'
})
export class HomeComponent
{
constructor(private modalService: MatDialog) {}
public openModal() : void
{
let dialog = this.modalService.open(RegistrationComponent, {});
}
}
registration.component.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { MatDialogRef } from '@angular/material/dialog';
import { User } from '../../../models/domain/User';
import { ApiUserService } from '../../api/entity-services/user.service';
import { AuthService } from '../../auth/auth.service';
import { AccountService } from '../services/account.service'
@Component({
selector: 'registration-component',
templateUrl: 'app/modules/account/templates/registration.component.html'
})
export class RegistrationComponent
{
public user :User = new User();
public errorMessage :string;
public isLoading :boolean;
constructor
(
private userService :ApiUserService,
private authService :AuthService,
private accountService :AccountService,
private router :Router,
public dialogRef :MatDialogRef<RegistrationComponent>
)
{
this.isLoading = false;
}
public onSubmit(e) :void
{
e.preventDefault();
this.isLoading = true;
this.userService
.Create(this.user)
.subscribe(
user =>
{
this.user.id = user.id;
this.user.login = user.login;
this.authService
.Login(this.user)
.subscribe(
token =>
{
this.accountService.Load()
.subscribe(
account =>
{
this.user = account;
this.isLoading = false;
this.dialogRef.close();
let redirectRoute = account.activeScopeId
? `/scope/${account.activeScopeId}`
: '/scope-list/';
this.router.navigate([redirectRoute]);
},
error => this.errorMessage = <any>error
);
},
error => this.errorMessage = <any>error
);
},
error => this.errorMessage = <any>error
);
}
}
Upvotes: 135
Views: 239871
Reputation: 1
For me, I found it was best to include the close function otherwise some errors could occur.
providers: [
{
provide: MatDialogRef,
useValue: {
close: (res: any) => {},
componentInstance: (res: any) => {},
},
}
],
Upvotes: 0
Reputation: 462
I had two situations where I encounter this issue:
When I was using Standalone Application/Components. I was able to use MatDialog but MatDialogRef was an issue. So I ended up using the original CDK DialogModule. And it worked perfectly.
I was using path alias in Angular 13. All the components that were being imported using path alias could not work with MatDialog or MatDialogRef. Using normal import solved the issue.
In summary, avoid importing MatDialog components with path alias, and in standalone applications, use CDK DialogModule, Dialog, DialogRef and everything will be ok. The configurations are mostly the same.
Upvotes: 0
Reputation: 131
in app.module.ts add in providers MatDialogRef and MAT_DIALOG_DATA and don't forget import in the same module:
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material/dialog';
...
imports: [MatDialogModule],
providers: [
{ provide: MatDialogRef, useValue: {} },
{ provide: MAT_DIALOG_DATA, useValue: {} },
],
...
Upvotes: 1
Reputation: 31
Not an answer for the question but might be helpful! if you have the NullInjectorError: No provider for MatDialogRef, MatDialogData error in the test file (.spec.ts) (it was my case), just add
imports: [MatDialogModule],
providers: [
{ provide: MatDialogRef, useValue: {} },
{ provide: MAT_DIALOG_DATA, useValue: {} },
],
in the TestBed.configureTestingModule of your component
Upvotes: 3
Reputation: 963
Don't provide dummy MatDialogRef or you will be unable to use it within the dialog component. For instance if you try to close the modal material will try to call .close()
on {}
because of the provide: MatDialogRef, useValue: {}
and throws.
Take a look at your module (answers above) & imports.
In my case, I unintentionally imported Dialog
from cdk instead of MatDialog
from material.
import { Dialog } from "@angular/cdk/dialog"; // wrong
...
constructor(private dialog: Dialog) {}
import { MatDialog } from "@angular/material/dialog"; // good
...
constructor(private dialog: MatDialog) {}
Upvotes: 3
Reputation: 1810
I had this issue a couple of times and in my case, I was trying to implement a modal with optional data passed to it. My solution was to add this piece of code to the parent module that implements the dialog/modal I was trying to display.
I tested this solution in case you implement the providers inside the app.module.ts
(Grand-parent, etc.), and it will still work.
// direct.parent.module.ts
// Import statements
import{...} from '';
import{<YOUR_COMPONENT>} from 'YOUR_COMPONENT_PATH';
...
@NgModule({
declarations: [..],
imports:[..],
providers: [ // <== This is the key that made it work
{
provide: MatDialogRef,
useValue: {}
},
{ provide: MAT_DIALOG_DATA, useValue: {} }, // <== I had to add this too
<YOUR_COMPONENT> // My Component
],
})
export class DirectParentModule { }
Upvotes: 1
Reputation: 53
Adding MatDialogModule to my app.module.ts - solved my problem.
import { MatDialogModule } from '@angular/material/dialog';
Upvotes: 1
Reputation: 6150
This error is generally caused by not providing the required modules. Import the outer module to your module where you are using the outer modules component. That will probably solve the problem.
Upvotes: 0
Reputation: 10313
I had this error when adding dialogs to a service to be shared in many components. Just to clarify, the error wasn't present in the application before moving dialogs to the service. The solution was to include a custom provider MatDialogRef
in the main module
import { DialogService } from './services/dialog.service';
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
...
imports: [
...
MatDialogModule
],
providers: [
{
provide: MatDialogRef,
useValue: {}
},
DialogService
],
...
With this provider the service worked as a singleton with my dialogs to be shared and the provider error was gone.
Upvotes: 199
Reputation: 273
in angular 12 in used "@Optional()" before inject mat dialog like below:
@Optional() @Inject(MAT_DIALOG_DATA) public data:any
and in main app module added some code like below:
providers: [
{
provide: MatDialogRef,
useValue: {}
}
],
best Regards.
Upvotes: 5
Reputation: 1779
Apparently everything was fine in my code. The problem was that while developing, I had a temporal route for my modal component so I could view it like a any other regular component/view. In the component, I had a button that triggers opening itself in a modal so I can test it how it looks when actually opened.
So I moved the code that opens the Dialog to another component and it seems to solve the issue.
Upvotes: 0
Reputation: 148
the imported paths in the component.ts and in spec.ts must be identical
for example:
// in the component and spec files
import { MatDialogRef } from '@angular/material/dialog';
or
// in the component and spec files
import { MatDialogRef } from '@angular/material';
Upvotes: 3
Reputation: 303
Just add @Optional()
before your dialogRef declaration.
For example:
constructor(
@Optional() public dialogRef: MatDialogRef<yourDialogComponentName>
) {
}
Upvotes: 12
Reputation: 2453
This error can be caused by injecting MatDialogRef
in the component calling MatDialog::open rather than in the component that is passed to the open method. The component passed to the MatDialog open method should have MatDialogRef
injected in its constructor as done in the example.
@Component({
selector: 'dialog-overview-example-dialog',
templateUrl: 'dialog-overview-example-dialog.html',
})
export class DialogOverviewExampleDialog {
constructor(
public dialogRef: MatDialogRef<DialogOverviewExampleDialog>,
@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
onNoClick(): void {
this.dialogRef.close();
}
}
Upvotes: 1
Reputation: 4093
For example you are using app-checkout
It could be happen if you use a component in both 'dialog' and 'normal' way add app-checkout
in normal html file.
Solution 1:
remove <app-checkout> </app-checkout>
if you dont need import it in normal way in html file
Solution 2 using in both dialog and html file. Instead of this:
// ... something have selector: "app-checkout",
constructor(
public dialogRef: MatDialogRef<CheckoutComponent>,
@Inject(MAT_DIALOG_DATA) public dialogData: any
) {}
you need to inject it (to make it optional inject):
this way:
constructor(
// only need the @Optional() before the public dialogRef
@Optional() public dialogRef: MatDialogRef<CheckoutComponent>,
@Inject(MAT_DIALOG_DATA) public dialogData: any
) {
}
or this way:
// ... the same above
private dialogRef = null;
private dialogData;
constructor(private injector: Injector) {
this.dialogRef = this.injector.get(MatDialogRef, null);
this.dialogData = this.injector.get(MAT_DIALOG_DATA, null);
}
Upvotes: 29
Reputation: 679
I had this Error and fixed it what you have to do is
check if you inserted import statement in the typescript file like this
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
check the constructor
constructor(@Optional() public dialogRef: MatDialogRef<GadgetAuthMessagesComponent>, @Inject(MAT_DIALOG_DATA) public message: string){ }
now go to module .ts and check the imports
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material/dialog';
in module.ts we need to put MatDialogModule name under imports array
MatDialogModule
now that's done finally we have to update the providers array
providers:
[{
provide: 'gadget-mlt',
useValue: GadgetMltComponent,
},
{provide:MatDialogRef , useValue:{} },
{ provide: MAT_DIALOG_DATA, useValue: {} }
],
Now It should work , Hope this Helps someone !
Upvotes: 8
Reputation: 329
Additionally to all of the above, You may also get this error if you have references to the Component selector in any of the template files in your app. MatDialog Components should only be invoked by the MatDialog.dialog.open() method and not through component selector
Unfortunately, the same error message may be thrown for many reasons.
Upvotes: 1
Reputation: 93
Remove dialogRef from the constructor:
https://stackblitz.com/edit/angular-dialog-update?file=src%2Fapp%2Fapp.component.ts
Upvotes: 1
Reputation: 1728
For me the problem was that I had added my Dialog component to some other HTML Template just to test it. Once I removed it, the error in OP went away and it just worked.
Upvotes: 3
Reputation: 87
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material';
Upvotes: 4
Reputation: 1872
Thanks to the @Edric, i'v solved the problem by importing MatDialogModule
, MatDialog
and MatDialogRef
from @angular/material/dialog
instead of @angular/material
Upvotes: 32
Reputation: 26821
It could be due to you not including a Web Animations API polyfill which is required for Angular animations to work since it relies on the API.
Here's a caniuse for the browsers that support it natively. Currently only Chrome, Firefox and Opera support the Web Animations API.
Anyway, you have to follow these steps to get a polyfill:
In the terminal, type the following in your console:
npm install web-animations-js
Once you have finished installing, uncomment the line for Angular Animations in polyfills.ts
(or add it if it's not there):
import 'web-animations-js'; // Uncomment this line
Alternatively, you can try importing the modules from the separate endpoints, like so:
From:
import { MatButtonModule, MatDialogModule } from '@angular/material';
To:
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
Upvotes: 4