NullInjectorError: No provider for MatDialogRef
AngularTypescriptAngular MaterialAngular5Angular Problem Overview
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
);
}
}
Angular Solutions
Solution 1 - Angular
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.
Solution 2 - Angular
Thanks to the @Edric, i'v solved the problem by importing MatDialogModule
, MatDialog
and MatDialogRef
from @angular/material/dialog
instead of @angular/material
Solution 3 - Angular
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);
}
Solution 4 - Angular
Just add @Optional()
before your dialogRef declaration.
For example:
constructor(
@Optional() public dialogRef: MatDialogRef<yourDialogComponentName>
) {
}
Solution 5 - Angular
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 !
Solution 6 - Angular
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';
Solution 7 - Angular
- In your module: importing only MatDialogModule from angular/material is sufficient. Not required to import and provide: MatDialogRef
- In your code where DialogComponent
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material';
- The above are the steps that I have followed. Not sure why you need to import it from the Dialog
- But, could you please clarify which selector you have used in your html/template? If you have used the "registration-component" in your template, that could be the reason why you would get this error. I tried out the exact same example out of the Material guide. I accidentally used the 'dialog-overview-example-dialog' instead of the 'dialog-overview-example'. = I got the same error you have got.
Solution 8 - Angular
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';
Solution 9 - Angular
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.
Solution 10 - Angular
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.
Solution 11 - Angular
Remove dialogRef from the constructor:
https://stackblitz.com/edit/angular-dialog-update?file=src%2Fapp%2Fapp.component.ts
Solution 12 - Angular
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();
}
}
Solution 13 - Angular
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.
Solution 14 - Angular
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.
Solution 15 - Angular
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.