How do I pass html to a template dialog component using Material with Angular 2/4

18,942

Updates

Update #1

The below code blocks are now updated to the latest version of @angular/material.

There is also a new example on how to pass custom HTML and it now shows how to pass the data to the dialog.

Update #2

DomSanitizer#sanitize should be used instead of DomSanitizer#bypassSecurityTrustHtml. (Thanks @binarylobster!)


Method 1 (Pipe)

To pass custom HTML, simply add an [innerHtml]="htmlContent" attribute with htmlContent as the sanitized version of HTML (in this case, a @Pipe()) to the selector (such as span):

my-dialog.component.html:

<h3 matDialogTitle>My Dialog</h3>
<mat-dialog-content>
  <div [innerHtml]="htmlContent | safeHtml"></div>
</mat-dialog-content>
<mat-dialog-actions>
  <button mat-button matDialogClose>Close Dialog</button>
</mat-dialog-actions>

my-dialog.component.ts:

import {Component} from '@angular/core';
// Other imports here

@Component({
  selector: 'my-dialog',
  templateUrl: 'my-dialog.component.html'
})
export class MyDialog {
  htmlContent: string;
}

safehtml.pipe.ts:

import { DomSanitizer } from '@angular/platform-browser';
import { Pipe, PipeTransform, SecurityContext } from '@angular/core';

@Pipe({ name: 'safeHtml'})
export class SafeHtmlPipe implements PipeTransform {
  constructor(private dom: DomSanitizer) {}
  transform(value) {
    // NOTE: Consider using DomSanitizer#sanitize instead of DomSanitizer#bypassSecurityTrustHtml, which executes code in `<script>` tags
    return this.dom.sanitize(SecurityContext.HTML, value);
  }
}

app.component.ts (Or wherever you would like to place the function):

import { MyDialog } from './my-dialog/my-dialog.component';
import { MatDialog } from '@angular/material/dialog';
export class AppComponent {
  constructor(private dialog: MatDialog){}
  htmlContent: string = '<p>Content goes here</p>';
  openDialog() {
    let dialogRef = this.dialog.open(MyDialog);
    dialogRef.componentInstance.htmlContent = this.htmlContent;
  }
}

Afterwards, declare the pipe in your module file:

@NgModule({
  declarations: [
    // Other declarations here
    SafeHtmlPipe
  ]
})
export class AppModule {}

Method 2 (DomSanitizer)

UPDATE: Another way to sanitize the HTML is as follows:

my-dialog.component.html:

<h3 matDialogTitle>My Dialog</h3>
<mat-dialog-content>
  <div [innerHtml]="htmlContent"></div>
</mat-dialog-content>
<mat-dialog-actions>
  <button mat-button matDialogClose>Close Dialog</button>
</mat-dialog-actions>

my-dialog.component.ts:

import { Component, OnInit } from '@angular/core';
import { SafeHtml } from '@angular/platform-browser';

@Component({
  selector: 'my-dialog',
  templateUrl: './my-dialog.component.html'
})
export class MyDialog {
  htmlContent: string;
}

app.component.ts:

import { MyDialog } from './my-dialog/my-dialog.component';
import { MatDialog } from '@angular/material/dialog';
import { DomSanitizer } from '@angular/platform-browser';
import { SecurityContext } from '@angular/core';

// ...
export class AppComponent {
  htmlContent: string = '<p>Content goes here</p>';
  constructor(private dialog: MatDialog, private dom: DomSanitizer){}

  openDialog() {
    let dialogRef = this.dialog.open(MyDialog);
    dialogRef.componentInstance.htmlContent = this.dom.sanitize(SecurityContext.HTML, this.htmlContent);
  }
}

Stackblitz demo (showcases both examples)

Share:
18,942
purplePanda
Author by

purplePanda

Updated on June 05, 2022

Comments

  • purplePanda
    purplePanda about 2 years

    I want to pass custom html from a specific page to a template component for dialog created using Material (MdDialog). Untill now I can pass simple data to the template like so:

        import { Component, OnInit, Input, TemplateRef } from '@angular/core';
        import { MdDialog, MdDialogConfig, MdDialogRef } from '@angular/material';
        import { DialogComponent } from './dialog.component';
    
    
        @Component({
          selector: 'app-commoncontent',
          template: '
           <div class="row  pull-right">
             <button md-raised-button (click)="open()" >{{"addButton" | translate}}
             </button>
           </div>',
          styleUrls: ['./commoncontent.component.css']
        })
        export class CommoncontentComponent implements OnInit {
          constructor(public dialog : MdDialog) { }
    
          ngOnInit() {
          }
    
          open() {
              let config = new MdDialogConfig()
              let dialogRef:MdDialogRef<DialogComponent> = 
              this.dialog.open(DialogComponent, config);
              dialogRef.componentInstance.content = "Hello Angular"
    
          }
        }
    
        import { Component, OnInit, Input, TemplateRef } from '@angular/core';
        import { MdDialogRef } from '@angular/material'
        import { CommoncontentComponent } from './commoncontent.component'
    
        @Component({
           selector: 'dialog-common',
           template: '
             <md-dialog-content class="accent-color">
                 <form class="form-horizontal" name="dialogForm">
                    {{content}} 
                 </form>
             </md-dialog-content>',
           styleUrls: ['./dialog.component.css']
        })
        export class DialogComponent {
          //@Input() templateDialog: TemplateRef<any>
          content:string;
          constructor(public dialogRef: MdDialogRef<DialogComponent>) {}
        }
    

    but I am unable to pass html. I know I can use ng-content for that but I couldn't manage to make it work.

  • binary lobster
    binary lobster about 6 years
    You should only use bypassSecurityTrustHtml if you really really need <script> content to be evaluated. If you're just trying to pass simple html like formatting, modify the above examples to use this.dom.sanitize(SecurityContext.HTML, this.htmlContent).
  • binary lobster
    binary lobster about 6 years
    Also, sanitize returns a string, so there should be no reason to declare htmlContent in the dialog component as SafeHtml.
  • harsh
    harsh almost 6 years
    Hi @Edric Thanks for above solution. However, what about passing complete html from component to dialog. example: <mat-form-field> <input matInput [(ngModel)]="name" placeholder="name" maxlength="4" required> </mat-form-field> In this case it still works however material css didn't get apply.
  • Edric
    Edric almost 6 years
    @harsh You can try using a DomPortalHost or a portal from the Angular CDK.
  • Edric
    Edric over 5 years
    Thanks for the tip @binarylobster! I didn't know that there was a sanitize method. Although the description for the DomSanitizer API does show: angular.io/api/platform-browser/DomSanitizer#sanitize