NullInjectorError: No provider for MatDialogRef

AngularTypescriptAngular MaterialAngular5

Angular 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

  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 !

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:

  1. In the terminal, type the following in your console:

    npm install web-animations-js
    
  2. 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

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionrc21View Question on Stackoverflow
Solution 1 - AngularLucasView Answer on Stackoverflow
Solution 2 - Angularrc21View Answer on Stackoverflow
Solution 3 - AngularHiep TranView Answer on Stackoverflow
Solution 4 - AngularJavedView Answer on Stackoverflow
Solution 5 - AngularIndika_Nuwan95View Answer on Stackoverflow
Solution 6 - AngularEdricView Answer on Stackoverflow
Solution 7 - AngularCharithView Answer on Stackoverflow
Solution 8 - AngularFuad CavadovView Answer on Stackoverflow
Solution 9 - AngularVIBrunazoView Answer on Stackoverflow
Solution 10 - AngularMohammad NaghshView Answer on Stackoverflow
Solution 11 - AngularGiollaView Answer on Stackoverflow
Solution 12 - AngularStack UnderflowView Answer on Stackoverflow
Solution 13 - AngularTheZergView Answer on Stackoverflow
Solution 14 - AngularO-9View Answer on Stackoverflow
Solution 15 - AngularAhmet ArslanView Answer on Stackoverflow