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>