Angular Materialでモーダルを実装したので、そのメモ。
出来上がりはこんな感じ。
構成はテーブル一覧のlistsコンポーネント
からdaialogコンポーネント
を呼び出すというもの。よくあるやつです。データを一覧で表示して、新規作成のボタンを押すとダイアログが表示されるみたいな。
app.module.ts
にAngularMaterial
をインポートしていくとごちゃごちゃするので実際は分割することが多いと思います。
// 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 {}
MaterialModule
にダイアログを表示するのに必要なMatDialogModule
とMatInputModule
をインポートします。
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 {}
次に呼び出しもとであるテーブルのListsComponent
です。ダイアログに必要ないものをは省略してます。
ポイントはconst dialogRef = this.dialog.open(DialogComponent, {
でDialogComponent
を依存性の注入(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 {
// ダイアログの押されたボタンの結果を格納する変数
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;
// ここからサービスなどにつなげてるなどして処理
console.log(this.value);
});
}
}
次は、ListsComponentのhtmlを作ります。ここでopenDialog()
を呼び出しています。
// 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>
最後に呼び出される側である。ダイアログを作ります。これはもう公式通りです。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() {}
}
最後にダイアログのhtmlを作ります。
// 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>
これで完成!