Create a Reusable Confirmation Dialog with Angular Material
Angular Material Reusable Confirm Dialog

Create a Reusable Confirmation Dialog with Angular Material

It is quite a common requirement for any application to prompt the user for a confirmation dialog to verify the action being taken. For instance, you may want to show a message when the user wants to delete a record or send an email. In this post, we will look at how we can implement a reusable component in Angular to achieve this.

Traditional Approach

Traditionally, web-based applications utilise the built-in JavaScript features to show alerts & dialogs as shown below. However, the vanilla JavaScript dialogs are synchronous – meaning everything on the screen will freeze until the user responds, they can’t be customised visually and don’t support images.

// Display a confirmation prompt
var result = confirm("Are you sure?");
Default JavaScript confirm dialog
Default JavaScript Confirmation Dialog

Custom Angular Confirm Dialog

To overcome the limitations of the traditional approach, we can easily build a flexible confirmation dialog in Angular with a bit of help from the Material components. Here is what we are going to build:

Angular Material Confirm Dialog Modal Popup
Custom Confirm Dialog in Angular Material

We will use the Dialog component of Angular Material library to display our confirm dialogs. The dialog takes the focus away from the current window, and forces the browser to read the message. The following are the main features of this custom component:

  • Asynchronous Behaviour: We want to show the dialog and subscribe to its result. This is very important as we don’t know when the user is going to respond. Asynchrony allows us to properly react to the response of the user.
  • Flexibility: We want to customise the title & message of the confirm dialog so that we can display any message from anywhere in the application.

You can get the full source code from GitHub. Alternatively, run the live demo below.

Import Angular Material

First of all, you need to import Angular Material to your application. If you need help with this, check out my blog post and learn how to properly import it.

Once you have access to Material components, import ButtonModule and MatDialogModule.

import { NgModule } from '@angular/core';
import { MatButtonModule, MatDialogModule } from '@angular/material';

@NgModule({
  imports: [
    MatButtonModule, MatDialogModule
  ],
  exports: [
    MatButtonModule, MatDialogModule
  ]
})
export class CustomMaterialModule {}

I am importing Material UI components to a feature module called CustomMaterialModule. You may wish to import them directly to the app.module.

Generate a Component

Next, generate a component for the confirmation dialog using the following command:

ng generate component ConfirmDialog

This will automagically create your component and link it with your root app.module. Open the app.module and add the newly-created component to the entryComponents array. This is so that the confirm dialog can be dynamically loaded into the view – read more about entry components.

import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { CustomMaterialModule } from './custom-material/custom-material.module';
import { ConfirmDialogComponent } from './confirm-dialog/confirm-dialog.component';

@NgModule({
  declarations: [
    AppComponent,
    ConfirmDialogComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    CustomMaterialModule
  ],
  providers: [],
  entryComponents: [ConfirmDialogComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

Implement Dialog Features

Basically, we just want to show a heading, message and buttons to dismiss the dialog. Here is what the view looks like:

<h1 mat-dialog-title>
  {{title}}
</h1>

<div mat-dialog-content>
  <p>{{message}}</p>
</div>

<div mat-dialog-actions>
  <button mat-button (click)="onDismiss()">No</button>
  <button mat-raised-button color="primary" (click)="onConfirm()">Yes</button>
</div>

As you can see, this is a standard Material dialog implementation. The component class to handle UI interaction is as follows:

import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { Component, OnInit, Inject } from '@angular/core';

@Component({
  selector: 'app-confirm-dialog',
  templateUrl: './confirm-dialog.component.html',
  styleUrls: ['./confirm-dialog.component.css']
})
export class ConfirmDialogComponent {
  title: string;
  message: string;

  constructor(public dialogRef: MatDialogRef<ConfirmDialogComponent>,
    @Inject(MAT_DIALOG_DATA) public data: ConfirmDialogModel) {
    // Update view with given values
    this.title = data.title;
    this.message = data.message;
  }
 
  onConfirm(): void {
    // Close the dialog, return true
    this.dialogRef.close(true);
  }

  onDismiss(): void {
    // Close the dialog, return false
    this.dialogRef.close(false);
  }
}

/**
 * Class to represent confirm dialog model.
 *
 * It has been kept here to keep it as part of shared component.
 */
export class ConfirmDialogModel {

  constructor(public title: string, public message: string) {
  }
}

The component just handles the events by closing the Material dialog with the selected result from the view. ConfirmDialogModel is used to pass data into the dialog.

Display Dialog on Button Click

Finally, we can show our custom confirmation dialog using the code below. Since we use MatDialog component internally, we take in the MatDialog dependency in the constructor and show the confirm dialog on button click. Subscribing to the afterClosed() event of the dialog means that we can get the result and update the view through data-binding. Add a button to the view to trigger the dialog, and a label to show the response:

<button mat-raised-button color="primary" (click)="confirmDialog()">Confirm</button>
<br>
Response is: {{result}}

and the component for the functionality:

import { Component } from '@angular/core';
import { ConfirmDialogModel, ConfirmDialogComponent } from './confirm-dialog/confirm-dialog.component';
import { MatDialog } from '@angular/material';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  result: string = '';

  constructor(public dialog: MatDialog) {}

  confirmDialog(): void {
    const message = `Are you sure you want to do this?`;

    const dialogData = new ConfirmDialogModel("Confirm Action", message);

    const dialogRef = this.dialog.open(ConfirmDialogComponent, {
      maxWidth: "400px",
      data: dialogData
    });

    dialogRef.afterClosed().subscribe(dialogResult => {
      this.result = dialogResult;
    });
  }
}

Summary

In conclusion, we looked at how we can create a reusable component in Angular to display confirmation dialogs. Similarly, this approach can be used to implement other types of dialogs such as alerts, date/time input dialogs & more.

Drop a comment below & subscribe for more šŸ˜Š

You can get the full source code from GitHub.

Umut Esen

Umut is an enthusiastic software developer, latest web and mobile technology adapter, freelance developer and primary author of onthecode.

Leave a Reply

Close Menu