Designing a Reusable Confirmation Dialog with Angular Material


Introduction

Showing confirmation dialog is very common in any application when the user performs any action. We can create a customized component for confirmation dialog that can be used in different components in the application. We will design this component using Angular Material Dialog which is a component to open modal dialogs with material styles. Now we will see how to design a reusable confirmation dialog.

Importing Angular Material

First of all, we need to import Angular material in our project. The pre-requisite for this is to have an existing Angular project. Using the below CLI command we will add Angular material to the project.
ng add @angular/material
Now the above command will install Angular Material, the CDK, and other Angular Animations. It will ask you to choose a default custom theme and setup browser animations as well. You can refer here to know how to get started with Angular Material.

Creating Confirm Dialog Module

We will have different files in the confirm dialog module. The confirm-dialog.component.html file, ts file, a service file, and a module file. We will see what module file includes:

// confirmation.dialog.module.ts file
import { NgModule} from '@angular/core';
import { ConfirmationDialogService } from './confirm-dialog.service';
import { MatDialogModule, MatButtonModule } from '@angular/material';
import { ConfirmationDialogComponent } from './confirm-dialog.component';
@NgModule({
    imports: [
        MatDialogModule,
        MatButtonModule
    ],
    declarations: [
        ConfirmationDialogComponent
    ],
    exports: [ConfirmationDialogComponent],
    entryComponents: [ConfirmationDialogComponent],
    providers: [ConfirmationDialogService]
  })
  export class ConfirmationDialogModule {
  }

Note: It should be noted that the component needs to be added in entryComponents to work.

Now we will create the design for the confirm dialog. Go to the below file confirmation.dialog.component.html file and write the below code. We are using MatDialog directives in the below code. 
  • Mat-dialog title - This applies to the heading element.
  • Mat-dialog content - This applies to scrollable content/description for the dialog.
  • Mat-dialog-action - This applies to the wrapper element for the action buttons at the bottom

// confirmation.dialog.module.html file
<div>
    <h2 mat-dialog-title>{{ data.title }} </h2>
</div>
<div mat-dialog-content>
    <div>{{ data.description }}</div>
</div>
<div mat-dialog-actions>
    <button class="btn btn-cancel" click="cancel()">{{ data.cancelText }}</button>
    <button class="btn" click="confirm()">{{ data.okText}}</button>
</div>
Inject MAT_DIALOG_DATA token, which can be used to access the data that is passed into the dialog. This will define the structure of the data. We will use different parameters here which are used for the dialog component i.e. cancelText, okText, title, and description of type string. MatDialogRef is also used here to reference the particular dialog component via MatDialog service.

// confirmation.dialog.module.ts file
import {  Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
@Component({
selector: 'app-confirmation-dialog',
templateUrl: './confirmation-dialog.component.html',

export class ConfirmationDialogComponent {

  constructor(@Inject(MAT_DIALOG_DATA) public data: {
                  cancelText: string,
                  okText: string,
                  title: string,
                  description: string}, 
              private matDialogRef: MatDialogRef<ConfirmationDialogComponent>) {}
              
  public cancel() {
    this.matDialogRef.close(false);
  }
  
  public confirm() {
    this.matDialogRef.close(true);
  }
}
Now we will see confirmation dialog service which we will be using in our components wherever we need a confirmation dialog popup.

import { Injectable } from '@angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { Observable } from 'rxjs';
import { ConfirmationDialogComponent } from './confirmation-dialog.component';
@Injectable()
export class ConfirmationDialogService {
  constructor(private dialog: MatDialog) { }
  dialogRef: MatDialogRef<ConfirmDialogComponent>;
  
  public open(params) {
    this.dialogRef = this.dialog.open(ConfirmationDialogComponent, {    
         data: {
           title: params.title,
           description: params.description,
           cancelText: params.cancelText,
           okText: params.okText
         }
    });
  }
  
  public confirm(): Observable<any> {    
    return this.dialogRef.afterClosed().subscribe(res => {
        return res;
      }
    ));
  }
}
The final module file:

import { CommonModule } from '@angular/common';
import { NgModule} from '@angular/core';
import { ConfirmationDialogService } from './confirm-dialog.service';
import { MatDialogModule, MatButtonModule } from '@angular/material';
import { ConfirmationDialogComponent } from './confirm-dialog.component';
@NgModule({
    imports: [
        CommonModule,
        MatDialogModule,
        MatButtonModule
    ],
    declarations:
    [
        ConfirmationDialogComponent
    ],
    exports: [ConfirmationDialogComponent],
    entryComponents: [ConfirmationDialogComponent], // Add the component to entryComponents without fail
    providers: [ConfirmationDialogService]
  })
  export class ConfirmationDialogModule {
  }

Using the Confirmation Service In Our Component

Follow the below steps to use this reusable service in different components. 
  • Import and inject the service in the component. 
  • 
    // component.ts file
    import { ConfirmationDialogService } from 'app/shared/confirm-dialog/confirm-dialog.service';
    @Component({
      selector: 'dialog-confirm-component',
      templateUrl: './dialog-confirm-component.html',
    })
    export class DialogConfirmComponent{
    
    	constructor(private confirmDialog: ConfirmationDialogService){}
    }
    
  • Calls the confirmDialog service with the required options. 
    
    const params = {
            title: "Delete user",
            description: "Are you sure you want to delete user ABC",
            cancelText: "Cancel",
            okText: "Ok"
    };
    this.confirmDialog.open(params); // Passing options to Dialog service
    this.confirmDialog.confirm().subscribe(result => {
       if (result) {
         //do something if confirmed is true
       }
    });
    

Comments