I implemented a modal with Angular Material, so here are my notes.
The result looks like this:
The structure is that you call the dialog component
from the lists component
(table list). This is a common pattern. You display a list of data, and when you click the new button, a dialog appears.
If you import AngularMaterial
into app.module.ts
, it can get messy, so it’s common to split it into modules.
// app.module.ts
// angular
import { MaterialModule } from './material.module';
// others
import { ListsComponent } from './lists.component';
import { DialogComponent } from './dialog.component';
@NgModule({
declarations: [
AppComponent,
listsComponent,
DialogComponent
],
imports: [
MaterialModule
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
In the MaterialModule
, import MatDialogModule
and MatInputModule
, which are necessary to display the dialog.
import { NgModule } from '@angular/core';
import { MatDialogModule } from '@angular/material/dialog';
import { MatInputModule } from '@angular/material/input';
@NgModule({
imports: [
MatDialogModule,
MatInputModule,
],
exports: [
MatDialogModule,
MatInputModule,
],
})
export class MaterialModule {}
Next is the ListsComponent
, which is the caller for the table. I have omitted things that are not necessary for the dialog.
The point is that const dialogRef = this.dialog.open(DialogComponent, {
is where DialogComponent
is injected via Dependency Injection (DI).
// lists.component.ts
// angular
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
// others
import { DialogComponent } from './dialog.component';
@Component({
selector: 'app-lists',
templateUrl: './lists.component.html',
styleUrls: ['./lists.component.css'],
})
export class ListsComponent implements OnInit {
// Variable to store the result of the button pressed in the dialog
value!: string;
constructor(
public dialog: MatDialog
) {}
ngOnInit(): void {
}
openDialog(): void {
const dialogRef = this.dialog.open(DialogComponent, {
data: { title: '新規作成' },
height: '300px',
width: '500px',
disableClose: false,
});
dialogRef.afterClosed().subscribe((result) => {
console.log('The dialog was closed');
this.value = result;
// Process the result, for example, by connecting to a service
console.log(this.value);
});
}
}
Next, let’s create the HTML for ListsComponent
. This is where openDialog()
is called.
// lists.component.html
<button
mat-fab
color="primary"
aria-label="Example icon button with a add icon"
(click)="openDialog()"
>
<mat-icon>add</mat-icon>
</button>
Finally, let’s create the dialog, which is the component being called. This is basically as per the official documentation. API reference for Angular Material dialog
// dialog.component.ts
import { Component, OnInit, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
export interface DialogData {
title: string;
data: string;
}
@Component({
selector: 'app-dialog',
templateUrl: './dialog.component.html',
styleUrls: ['./dialog.component.css'],
})
export class DialogComponent implements OnInit {
constructor(
@Inject(MAT_DIALOG_DATA)
public data: DialogData,
public matDialogRef: MatDialogRef<DialogComponent>
) {}
ngOnInit() {}
}
Finally, let’s create the HTML for the dialog.
// dialog.component.html
<h3 mat-dialog-title>{{ data.title }}</h3>
<mat-dialog-content>
<mat-form-field>
<mat-label>value</mat-label>
<input matInput [(ngModel)]="data.data" />
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions>
<table cellspacing="15">
<tr>
<td>
<button
mat-raised-button
[mat-dialog-close]="data.data"
cdkFocusInitial
>
作成
</button>
</td>
<td>
<button mat-button mat-dialog-close>キャンセル</button>
</td>
</tr>
</table>
</mat-dialog-actions>
And that’s it!