NullInjectorError: No provider for MatDialogRef
Solution 1
Thanks to the @Edric, i'v solved the problem by importing MatDialogModule
, MatDialog
and MatDialogRef
from @angular/material/dialog
instead of @angular/material
Solution 2
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 3
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
Just add @Optional()
before your dialogRef declaration.
For example:
constructor(
@Optional() public dialogRef: MatDialogRef<yourDialogComponentName>
) {
}
Solution 5
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 !
rc21
Updated on January 05, 2022Comments
-
rc21 over 2 years
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 ); } }
-
rc21 over 6 yearsThanks, @Edric, using polyfill hasn't helped me, but idea with importing modules from the separate endpoints has resolved the problem.
-
ASHUTOSH over 5 yearsBrilliant! I had to also add
{provide:MAT_DIALOG_DATA,useValue:{}
-
VIBrunazo almost 5 years@MorloMbakop Ouch, that was my problem. I had reference my Dialog component in some Template just to test it. Once I removed it, then it worked with no errors without adding anything to providers. Thanks!
-
Gagan over 4 yearsIn my case I had this error while using MatDialogRef inside a Guard. Adding in the providers array, as stated above in the answer, solved it.
-
Rusty Rob about 4 yearsyou can also go like this right: constructor(@Optional() private ref: MatDialogRef<EditPersonComponent>,)
-
Hiep Tran about 4 yearsI tried but it not work, did you try this? @robertking
-
Rusty Rob about 4 yearsyeah it worked for me :) ref was null unless the component is opened inside a dialog
-
Tim Harker almost 4 yearsAdding
MatDialogModule
from@angular/material
solved it for me. -
Brian Edwards over 3 yearsThis was awesome, the Providers fixed it for me. Thanks!
-
Sankofa over 2 yearsAdding a little more, I had to use: ``` const mockDialogRef = { close: jasmine.createSpy('close') }; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ MatDialogModule], declarations: [DialogOverviewComponent], schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA], providers: [ { provide: MatDialogRef, useValue: mockDialogRef } ], }) .compileComponents(); })); ```
-
dmboucher over 2 yearsSame - providers fixed it. Thanks!!
-
Kim Phung about 2 years@Optional() is save my life.