DEV Community

Ram Kota
Ram Kota

Posted on

How to reuse Angular Material Dialog with dynamic content

I have a Angular Material Dialog Component that takes Inputs and uses them in header and footer of modal. I want to pass some html elements in modal's body section from a component.

dashboard.component.html displays a 'show/hide columns' button.

dashboard.component.html

<app-modal [title]="title" [btnText]="text'>
   <section #template>
    <mat-form-field appearance="outline" *ngIf="!showForm && viewParams.length > 0 && cn_hostname_index >= 0">
      <mat-label>Search Columns</mat-label>
      <input 
        matInput
        id="columnSearchTxt"
        placeholder="Search Columns"
        name="columnSearchTxt"
        [(ngModel)]="colSearch.title"
      />
      <button *ngIf="colSearch.title" (click)="colSearch.title = ''" mat-icon-button matSuffix (click)="searchHosts()" matTooltip="Filter on hostname">
        <mat-icon aria-hidden="false" aria-label="Clear">close</mat-icon>
      </button>
    </mat-form-field>

    <mat-slide-toggle
      *ngFor="let col of colDefs | filter: 'title':colSearch.title"
      color="primary"
      [name]="col.title"      
      [(ngModel)]="col.includeField"
      labelPosition= "before"
    >
      {{ col.title }}
    </mat-slide-toggle>
   </section>
</app-modal>
Enter fullscreen mode Exit fullscreen mode

modal.component.ts

import { Component, Inject, Input, TemplateRef, ViewChild } from '@angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';

export interface DialogData {
  title: string;
  text: string;
  template: TemplateRef<any>
}

@Component({
  selector: 'app-modal',
  template: `<button mat-raised-button (click)="openDialog()">{{ btnText }}</button>`,
  styleUrls: ['./modal.component.scss']
})
export class ModalComponent {

  @Input() btnText: string;
  @Input() id: string;
  @Input() modalTitle: string;
  @Input() okText: string;
  @Input() name: string;
  @ViewChild('template') template: TemplateRef<any>;

  constructor(public dialog: MatDialog) { }

  openDialog(): void {
    const dialogRef = this.dialog.open(ModalDialogComponent, {
      data: {
        id: this.id, 
        title: this.modalTitle, 
        text: this.okText, 
        name: this.name,
        template: this.template
      },
    });
  }

}

@Component({
  selector: 'modal-dialog',
  templateUrl: './modal-dialog.component.html',
})
export class ModalDialogComponent {
  constructor(
    public dialogRef: MatDialogRef<ModalDialogComponent>,
    @Inject(MAT_DIALOG_DATA) public data: DialogData,
  ) {}

  onNoClick(): void {
    this.dialogRef.close();
  }
}
Enter fullscreen mode Exit fullscreen mode

modal-dialog.component.html

<section>
    <div>
        <mat-icon (click)="onNoClick()" aria-hidden="false" aria-label="close icon">close</mat-icon>
    </div>
    <h1 mat-dialog-title>{{ data.title }}</h1>
    <div mat-dialog-content>
        <!-- Want to display html elements from app-modal -->
    </div>
    <div mat-dialog-actions>
        <button mat-button (click)="onNoClick()">{{ data.text ? data.text : 'Ok' }}</button>
    </div>
</section>
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
jackobean profile image
Jackobean

codegram.com/blog/playing-with-dia...

Seems to be similar to what you are looking for! I still dont fully get the context and I havent been able to dynamically set the input and outputs as for some reason they are initialised at the same time that the parent element is and so not updated when the values are updated but its close! maybe you will be able to figure it out! all the best, J