15

Before marking this question as "duplicate", kindly hear me out since I'm stuck for hours with this problem. I've gone through the existing questions but could not find any solution.

I'm learning Angular and have started with Angular 9+ and Angular Material. I'm trying to implement a simple dialog of Angular Material by reading the documentation from the official page.

My code closely follows the example code but I'm at a loss on why I'm still getting this error messages:

'mat-dialog-content' is not a known element.
'mat-dialog-actions' is not a known element.

The dialog does show up but it looks as if no Angular Material components / directives are being rendered at all in the dialog template html. Even if I use <button mat-button>Button</button>, it would be rendered as a normal button and not an Angular Material button. Everything else which is not in the dialog template works perfectly fine. I have no idea what I'm doing wrong here, but if anyone could point me out my mistake, that'd be great!

app.module.ts: (I'm importing the MatDialogModule)

...
import { MatDialogModule } from '@angular/material/dialog';

@NgModule({
    declarations: [
        ...
    ],
    imports: [
        ...
        MatDialogModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }

mycomponent.ts:

import { Component, OnInit, ViewChild, Inject } from '@angular/core';
import { MatDialog, MatDialogModule, MAT_DIALOG_DATA, MatDialogConfig } from '@angular/material/dialog';
...

@Component({
  selector: 'app-my',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.css']
})
export class MyComponent implements OnInit {

    constructor(public dataDialogHandler: MatDialog) {}

    ngOnInit(): void {}

    public openDataDialog(): void {

        const dialogConfig = new MatDialogConfig();

        dialogConfig.data = {};

        this.dataDialogHandler.open(DataDialogComponent, dialogConfig);
    }
}

@Component({
    selector: 'data-dialog',
    templateUrl: './data-dialog.html'
})
export class DataDialogComponent {

    constructor(@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
}

export interface DialogData {}

data-dialog.html:

<h2 mat-dialog-title>some title</h2>
<mat-dialog-content>
    <p>dialog works</p>
</mat-dialog-content>
<mat-dialog-actions align="end">
    <button mat-button mat-dialog-close>Close</button>
</mat-dialog-actions>

and finally, in my.component.html:

<button mat-button (click)="openDataDialog()">View Dialog</button>

What am I doing wrong here? Thanks in advance!

@angular/core 9.0.7
@angular/cdk 9.1.3
@angular/material 9.1.3
typescript 3.7.5
Sajib Acharya
  • 1,666
  • 5
  • 29
  • 54

6 Answers6

18

Change the mat-dialog-content and mat-dialog-actions to attributes. i.e:

<div mat-dialog-content>
    <p>dialog works</p>
</div>
<div mat-dialog-actions align="end">
    <button mat-button mat-dialog-close>Close</button>
</div>
Danilo Mz
  • 489
  • 3
  • 8
  • 3
    This solved my problem working with Angular 11 – wbartussek Mar 04 '21 at 15:29
  • I was migrating from angular & material 7 to 11 . Ng update should have taken care this but not. I had to make changes manually. – Ahmed Jun 02 '21 at 15:20
  • This was super frustrating to figure out. Thank you so much. – Stevers Nov 19 '21 at 05:41
  • I wonder why its working after changing a tag into property. – Abdul Jun 25 '22 at 16:23
  • Strange, I was already on version 12 and it worked. On migration to version 13 began to complain. – FXLima Sep 12 '22 at 17:54
  • Cause: Updating the component has changed the name of your module. It was with the wrong name in the shared.module, it caused an error in the compilation. This error was not accused, it was hidden, showing the error treated in this post. See if you're not having the same problem and looking for the wrong cause. – FXLima Sep 13 '22 at 12:24
11

Please add DataDialogComponent in the declarations array, and in entryComponents array of app.module.ts

import { MatDialogModule } from '@angular/material/dialog';

@NgModule({
    declarations: [
       DataDialogComponent //I think you have missed this declaration
    ],
    imports: [
        ...
        MatDialogModule
    ],
    providers: [],
   entryComponents: [DataDialogComponent]
    bootstrap: [AppComponent]
})
export class AppModule { }
sattva_venu
  • 677
  • 8
  • 22
1

I had the same problem and solved it by moving the dialog component and the container components into different files. At the moment you've got this setup where both the dialog and the container component are declared in the same file:

# my.component.ts

@Component({
  selector: 'app-my',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.css']
})
export class MyComponent implements OnInit {

    constructor(public dataDialogHandler: MatDialog) {}

    ngOnInit(): void {}

    public openDataDialog(): void {

        const dialogConfig = new MatDialogConfig();

        dialogConfig.data = {};

        this.dataDialogHandler.open(DataDialogComponent, dialogConfig);
    }
}

@Component({
    selector: 'data-dialog',
    templateUrl: './data-dialog.html'
})
export class DataDialogComponent {

    constructor(@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
}

export interface DialogData {}

Split the components into separate files

I would suggest creating an entirely new dialog component that handles its own dependencies so that you end up with this:

# my.component.ts

import { Component} from '@angular/core';
import{ MatDialog } from '@angular/material/dialog';

# Make sure you import your newly created component
import{ MyDataDialog } from 'src/app/wherever-youve-put-it/my-data-dialog.component';

@Component({
  selector: 'app-my',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.css']
})
export class MyComponent implements OnInit {

    constructor(public dataDialogHandler: MatDialog) {}

    ngOnInit(): void {}

    public openDataDialog(): void {

        const dialogConfig = new MatDialogConfig();

        dialogConfig.data = {};

        this.dataDialogHandler.open(MyDataDialogComponent, dialogConfig);
    }
}

Then use ng generate component my-data-dialog to create a new component to be your dialog. You can then copy across dependencies and code into (you'll be less likely to get references etc. wrong if you use the CLI to generate it and copy rather than just copy into a new handcrafted component)

# my-data-dialog.component.ts

import { Component, OnInit, Inject} from '@angular/core';
import{ MAT_DIALOG_DATA } from '@angular/material/dialog';

@Component({
    selector: 'data-dialog',
    templateUrl: './data-dialog.html'
})
export class DataDialogComponent {

    constructor(@Inject(MAT_DIALOG_DATA) public data: DialogData) {}
}

export interface DialogData {}
Peter Nixey
  • 16,187
  • 14
  • 79
  • 133
  • So I was trying a few ways regarding this. The way I found that it works 100% of the time is by adding the Dialog Component in the declarations of 1app.module` and also importing `MatDialogModule` and (optionally) `MatButtonModule` to `app.module`'s imports. Weird that this works for some reason. – Sajib Acharya Aug 28 '20 at 16:23
0

Finally I got a solution for my problem!

Needed to answer here because I think it's the same thing. It'll help a lot of people for sure!

So, there are two problems: The firt is that you aren't exporting 'MyComponent'.

@NgModule({
    declarations: [
        ...
    ],
    imports: [
        ...
        MatDialogModule
    ],
    providers: [],
    bootstrap: [AppComponent]
    exports: [ AppComponent,         #add this code
              MyComponent ],
})

It seems that angular can't bind your imports in a class that isn't exported. Well that solved the problem in HTML file. Now the second one: for the test, after you add your component in your "module.ts", you need to add the MatDialogModule in "spec.ts" too:

beforeEach(async() => {
await TestBed.configureTestingModule({
  imports: [ CommonModule,
    ...,
    MatDialogModule],

After these changes it worked fine.

0

It seems that the current Material docs:

<h2 mat-dialog-title>Delete all elements?</h2>

This will delete all elements that are currently on this page and cannot be undone. Cancel

<button mat-button [mat-dialog-close]="true">Delete

and here

Do not work for Angular 12. The solution above by Danilo Mz worked for me.

Ie: " Change the mat-dialog-content and mat-dialog-actions to attributes"

-1

You are missing the entryComponents declaration.

Also add interface for DialogData

export interface DialogData {
 example: string;
}

Live: https://stackblitz.com/edit/angular-q4mwkt

MatDialog - Medium Post

Prakash M.
  • 479
  • 8
  • 26
  • I tried this, by adding `DataDialogComponents` to `entryComponents`. But this still does not solve the issue. – Sajib Acharya Mar 21 '20 at 16:10
  • It works well for me with the exact code that you have shared - https://stackblitz.com/edit/angular-q4mwkt – Prakash M. Mar 21 '20 at 16:42
  • Make sure you have compatible versions of core, common, compiler, cdk, material and animations in package.json – Prakash M. Mar 21 '20 at 16:43
  • Do spelling check as well. I see that you have mentioned `DataDialogComponents` in the comments whereas in the question it is `DataDialogComponent` in singular form. – Prakash M. Mar 21 '20 at 16:47
  • Okay I looked into your stackbliz code and it doesn't work there. If you open the dialog, look how you've used mat-button but the dialog only shows a normal html button. – Sajib Acharya Mar 21 '20 at 17:12
  • 1
    I thought your issue was mat-dialog not showing up. You have to import every material module if you want to make use of them. Now I have updated the stackblitz by importing the mat-button module as well. – Prakash M. Mar 21 '20 at 17:24
  • I only copy pasted your code and I did not try to do anything extra to make it work. – Prakash M. Mar 21 '20 at 17:29