Display HTML in Angular  Components

How to safely display any HTML in an Angular component without escaped or encoded characters.

Displaying HTML in an Angular component that’s stored in a template variable isn’t as straightforward as you’d expect. In order to properly store and display an HTML string in a component without issues, you’ll need to take one of two approaches depending on the tags and attributes in the HTML. If you’ve tried displaying HTML in your component with the standard template binding syntax ({{ var }}) you’ll end up with escaped HTML output. There’s a way around this and many of the other common headaches associated with Angular and storing HTML in a variable. Below are two explanations along with helpful examples of each approach that should hopefully make the process simple and easy for you.

Simple Scenarios with Basic HTML

In most cases you can get by with using the [innerHTML] attribute, but only if your content is considered safe from XSS. In this context, safe means it doesn’t contain any tags or attributes that can be used to inject JavaScript. Let’s look at a basic working example.

Component TypeScript

/**
 * Basic HTML Component Usage
 */
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'some-component',
  templateUrl: 'some-component.html',
})
export class SomeComponent implements OnInit {
  html: string;

  constructor() {}

  ngOnInit(): void {
    this.html = `<h2>We're currently undergoing essential maintenance, we'll be back online shortly.</h2>
    <p>If you have any questions please contact our customer services team via email at <a href="mailto:[email protected]?subject=Support Requested">[email protected]</a></p>`;
  }
}

Component Template

<section class="content" *ngIf="html" [innerHTML]="html"></section>

Rendered HTML Output

<section class="content">
   <h2>We're currently undergoing essential maintenance, we'll be back online shortly.</h2>
   <p>If you have any questions please contact our customer services team via email at <a href="mailto:[email protected]?subject=Support Requested">[email protected]</a></p>`;
</section>

If you’ve tried this approach and your HTML is mysteriously missing certain HTML tags, such as an <svg> element, then you’ll need to take a more advanced approach (see the second example below) to make sure Angular considered your HTML safe. (assuming it is)

Advanced Scenarios with Potentially Unsafe HTML

Angular includes a built-in DomSanitizer that helps protect your app from Cross Site Scripting Security bugs (XSS). This class works by sanitizing values so that any HTML text used in a component is safe to add to the DOM in a browser environment. If you’re trying to display HTML with any tag or property that can be used to inject or execute JavaScript, then it’s considered unsafe by the DomSanitizer.

To get around this you can use store the component DomSanitizers bypassSecurityTrustHtml method to mark your HTML as a SafeHtml type. It’s crucial that you understand why this exists: to make sure you don’t expose your app to XSS attacks. Below is a basic example of a component in action.

Component TypeScript

/**
 * Advanced HTML Component Usage
 */
import { Component, OnInit } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

@Component({
  selector: 'some-component',
  templateUrl: 'some-component.html',
})
export class SomeComponent implements OnInit {
  html: SafeHtml;

  constructor(private sanitizer: DomSanitizer) {}

  ngOnInit(): void {
    const template = `<svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 512 512">
      <path d="M256 48C141.1 48 48 141.1 48 256s93.1 208 208 208 208-93.1 208-208S370.9 48 256 48zm17.2 109.6l-3.1 115.1c-.2 8.2-5.9 14.8-14.1 14.8s-13.9-6.6-14.1-14.8l-3.1-115.1c-.2-9.6 7.5-17.6 17.2-17.6 9.6 0 17.4 7.9 17.2 17.6zM256 354c-10.7 0-19.1-8.1-19.1-18.4s8.4-18.4 19.1-18.4c10.7 0 19.1 8.1 19.1 18.4S266.7 354 256 354z"/>
    </svg>
    <h2>We're currently undergoing essential maintenance, we'll be back online shortly.</h2>
    <p>If you have any questions please contact our customer services team via email at <a href="mailto:[email protected]?subject=Support Requested">[email protected]</a></p>`;

    this.html = this.sanitizer.bypassSecurityTrustHtml(template);
  }
}

Component Template

<section class="content" *ngIf="html" [innerHTML]="html"></section>

Rendered HTML Output

<section class="content">
   <svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 512 512">
      <path d="M256 48C141.1 48 48 141.1 48 256s93.1 208 208 208 208-93.1 208-208S370.9 48 256 48zm17.2 109.6l-3.1 115.1c-.2 8.2-5.9 14.8-14.1 14.8s-13.9-6.6-14.1-14.8l-3.1-115.1c-.2-9.6 7.5-17.6 17.2-17.6 9.6 0 17.4 7.9 17.2 17.6zM256 354c-10.7 0-19.1-8.1-19.1-18.4s8.4-18.4 19.1-18.4c10.7 0 19.1 8.1 19.1 18.4S266.7 354 256 354z"></path>
   </svg>
   <h2>We're currently undergoing essential maintenance, we'll be back online shortly.</h2>
   <p>If you have any questions please contact our customer services team via email at <a href="mailto:[email protected]?subject=Support Requested">[email protected]</a></p>`;
</section>

There you have it! These two approaches should cover any scenario where you need to embed HTML in an Angular component, regardless of the tags and properties it contains. It’s important to understand that when you use the advanced approach described above you bypass XSS checks, and you may be exposing your application to security issues. If you’re embedding HTML content from an API response in your Angular component template make sure that the HTML returned is safe and you should be alright.

Meet the Author

Kevin Leary, WordPress Consultant

I'm a freelance web developer and WordPress consultant in Boston, MA with 17 years of experience building websites and applications. View a portfolio of my work or request an estimate for your next project.