Home > Software design >  Create a reusable dialog in Angular
Create a reusable dialog in Angular

Time:01-14

I want to create a reusable dialog in Angular. For example, a dialog might consist of just a title, a message, and a yes/no button. Another dialog could also have a dropdown. The function called when you click Yes or No is different for each dialog.

How can I implement this?

This is what my current code looks like. So far I've only managed to make my title, message and button texts dynamic.

dialog.component.html

<h1 mat-dialog-title>{{data?.title}}</h1>
<div mat-dialog-content>
  {{data?.message}}
</div>
<div mat-dialog-actions>
  <button mat-raised-button mat-dialog-close>{{data?.confirmText}}</button>
  <button mat-raised-button mat-dialog-close cdkFocusInitial>{{data?.cancelText}}</button>
</div>

dialog.component.ts

import { DialogData } from './../../models/dialog-data';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { Component, OnInit, Inject } from '@angular/core';

@Component({
  selector: 'app-dialog',
  templateUrl: './dialog.component.html',
  styleUrls: ['./dialog.component.scss'],
})
export class DialogComponent implements OnInit {
  constructor(@Inject(MAT_DIALOG_DATA) public data: DialogData) {}

  ngOnInit(): void {}
}

dialog.service.ts

export class DialogService {

  constructor(private dialog: MatDialog) { }

  openDialog(data: DialogData): Observable<boolean> {
    return this.dialog.open(DialogComponent, {
      data,
      width: '400px',
      disableClose: true
    }).afterClosed();
  }
}

dialog-data.ts

export interface DialogData {
  title: string;
  message: string;
  confirmText: string;
  cancelText: string;
}

openDialog()

openDialog() {
    this.dialogService.openDialog({
      title: 'Title',
      message: 'message',
      confirmText: 'Yes',
      cancelText: 'No',
    });
  }

CodePudding user response:

You can write the code for "OK" and "Cancel" functions in two ways:

  1. If you are closing the dialog on click of "OK" and "Cancel" then write the code in afterclosed:

    const dialogRef = this.dialog.open(ConfirmDialogComponent, { data: { title: 'Title', message: 'message', confirmText: 'Yes', cancelText: 'No', });

    dialogRef.afterClosed().subscribe(confirm => { if (confirm) { // do something on "OK" click } else{ // do something on "OK" click } });

  2. If you are not closing the dialog on "OK" and "Cancel" click:

You have to pass data while calling the dialog with an injectable data:

 const dialogRef = this.dialog.open(ConfirmDialogComponent, { 
data: { 
title: 'Title',
 message: 'message',
 confirmText: 'Yes',
 cancelText: 'No', 
isDataFromHome:true //pass a variable from another components as well and check the value of this variable in dialog component, on the basis of which you can define different functions on OK and Cancel
});

CodePudding user response:

If you don't need absolute flexibility then it makes sense to create two different dialog components and trigger corresponding dialog depending on input parameters, similarly you can use ngSwitch/ngIf in the dialog component to show input depending on the provided parameters. If you still want flexibility then you can pass TemplateRef in the dialog parameters and render input component dynamically.

CodePudding user response:

You could take advantage Content Projection for specifying the dynamic content of the dialog parts.

Dialog.html:

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

        <div >
            <ng-content select=".content">
            </ng-content>
        </div>
    </mat-dialog-content>

    <mat-dialog-actions>
        <div >
            <ng-content select=".buttons">
            </ng-content>
        </div>
    </mat-dialog-actions>
</div>

Ok dialog (just title and ok button):

<my-dialog [title]="title">
    <div >
        <button mat-flat-button color="primary" (click)="onOk()">
            {{ okText }}
        </button>
    </div>
</my-dialog>
  • Related