NullInjectorError: No provider for MatDialogRef

125,849

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

  1. check if you inserted import statement in the typescript file like this

    import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";

  2. check the constructor

      constructor(@Optional() public dialogRef: MatDialogRef<GadgetAuthMessagesComponent>, @Inject(MAT_DIALOG_DATA) public message: string){ }
    
  3. now go to module .ts and check the imports

    import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material/dialog';
    
  4. in module.ts we need to put MatDialogModule name under imports array

    MatDialogModule

  5. 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 !

Share:
125,849
rc21
Author by

rc21

Updated on January 05, 2022

Comments

  • rc21
    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
    rc21 over 6 years
    Thanks, @Edric, using polyfill hasn't helped me, but idea with importing modules from the separate endpoints has resolved the problem.
  • ASHUTOSH
    ASHUTOSH over 5 years
    Brilliant! I had to also add {provide:MAT_DIALOG_DATA,useValue:{}
  • VIBrunazo
    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
    Gagan over 4 years
    In 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
    Rusty Rob about 4 years
    you can also go like this right: constructor(@Optional() private ref: MatDialogRef<EditPersonComponent>,)
  • Hiep Tran
    Hiep Tran about 4 years
    I tried but it not work, did you try this? @robertking
  • Rusty Rob
    Rusty Rob about 4 years
    yeah it worked for me :) ref was null unless the component is opened inside a dialog
  • Tim Harker
    Tim Harker almost 4 years
    Adding MatDialogModule from @angular/material solved it for me.
  • Brian Edwards
    Brian Edwards over 3 years
    This was awesome, the Providers fixed it for me. Thanks!
  • Sankofa
    Sankofa over 2 years
    Adding 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
    dmboucher over 2 years
    Same - providers fixed it. Thanks!!
  • Kim Phung
    Kim Phung about 2 years
    @Optional() is save my life.