Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Material: 'mat-dialog-content' is not a known element

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
like image 573
Sajib Acharya Avatar asked Mar 21 '20 15:03

Sajib Acharya


3 Answers

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>
like image 134
Danilo Mz Avatar answered Oct 17 '22 22:10

Danilo Mz


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 { }
like image 11
sattva_venu Avatar answered Oct 17 '22 21:10

sattva_venu


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 {}
like image 1
Peter Nixey Avatar answered Oct 17 '22 21:10

Peter Nixey