Overview
Getting modals working in Angular + Material took me a lot longer than I expected. But I must confess that the documentation for them here -> https://material.angular.io/components/dialog/overview was spot on. You just have to actually read all of it.
I’m going to provide a shorter crash course here showing 100% of what you need code-wise. I suggest you refer to that main link to understand everything fully though.
Requirements Summary
To get a modal working, assuming you already have Angular + Material working, you need to do the following. This assumes you are just using the root @NgModule in app.module.js, but you can use other modules if you like.
-
import MatDialogModule at the top of your app.module.ts and it to your imports array in the same file.
-
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} and {Inject} in your current page’s .ts file.
- Create a new HTML file for your modal at the same level as your current page.
- Add a dialog component into your typescript file.
- Write code to trigger your dialog to open.
- Import your dialog component back in your app.module.js and register it as a declaration *and* as an entry component (you probably have to add entry components as they’re not there by default).
- This is because dialogs are created on-the-fly and angular needs extra information to deal with ad-hoc components.
Detailed Code Example
app.module.ts
Again, if you have a multi @NgModule angular app, you can still refer to this but you may put the content in other modules.
//... (normal imports left out for brevity) import { MatDialogModule} from '@angular/material'; import { DialogOverviewExampleDialog } from "./cs-job-monitor/cs-job-monitor.component" @NgModule({ declarations: [ ..., DialogOverviewExampleDialog ], imports: [ ... MatDialogModule ], providers: [], bootstrap: [AppComponent], entryComponents: [ DialogOverviewExampleDialog ], }) export class AppModule { }
cs-job-monitor.component.ts
This is just one of the pages in my angular project as generated by the angular CLI. It just happens to be called cs-job-monitor but that isn’t important to you.
//... (normal imports left out for brevity) import { Inject } from '@angular/core'; import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material'; //Your normal page component. @Component({ selector: 'app-cs-job-monitor', templateUrl: './cs-job-monitor.component.html', styleUrls: ['./cs-job-monitor.component.styl'] }) export class CsJobMonitorComponent { constructor(private http: HttpClient, public dialog: MatDialog) { //Normal work. } //In my case, I am opening the modal on the "on select row" event //of an angular grid (ag-grid). But this is not important, just look /at how it opens. onSelectionChanged(event: Object) { const dialogRef = this.dialog.open(DialogOverviewExampleDialog, { data: event["api"].getSelectedRows() }); } } //Here's your dialog component. Mine is still named after the example one from //angular's documentation page (I'll fix that!). But it works fine. @Component({ selector: 'dialog-overview-example-dialog', templateUrl: 'dialog-overview-example-dialog.html' }) export class DialogOverviewExampleDialog { constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: DialogData) {} onNoClick(): void { this.dialogRef.close(); } }
dialog-overview-example-dialog.html
Here is the HTML that appears in your dialog when it pops up. For now, I just have it displaying the object you gave it as data as JSON. In this case, as it will display the selected rows from the ag-grid I was using to call onSelectionChanged(). But I’m not bothering to add that here.
<pre> {{data | json}} </pre>