shou2017.com
JP

Implementing a modal with Angular Material

Sat Sep 24, 2022
Sat Aug 10, 2024

I implemented a modal with Angular Material, so here are my notes.

The result looks like this:

Implementing a modal with Angular Material

Environment

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

Structure

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.

Angular Material

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 {}

Create the Caller for the Dialog

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>

Create the Dialog

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!

See Also