shou2017.com
JP / EN

AngularMaterialでモーダル実装

Sat Sep 24, 2022
Sat Aug 10, 2024

Angular Materialでモーダルを実装したので、そのメモ。

出来上がりはこんな感じ。

AngularMaterialでモーダル実装

環境

  • “@angular/cli”: “~14.1.0”,
  • “typescript”: “~4.7.2”
  • “@angular/material”: “^14.1.0”

構成

構成はテーブル一覧のlistsコンポーネントからdaialogコンポーネントを呼び出すというもの。よくあるやつです。データを一覧で表示して、新規作成のボタンを押すとダイアログが表示されるみたいな。

AngularMaterial

app.module.tsAngularMaterialをインポートしていくとごちゃごちゃするので実際は分割することが多いと思います。

// 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にダイアログを表示するのに必要なMatDialogModuleMatInputModuleをインポートします。

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>

これで完成!

See Also