If you're working on an Angular app and you get an HTML response from a downstream microservice (hello, Gmail!), you might see quirky results when you try to display the HTML on the screen.

That's because Angular takes the liberty of "sanitizing" the HTML. It does that for your own good.

You see, Angular is trying to prevent a cross-site scripting (XSS) threat. And that's a good thing.

Take a look at the console log and you'll see the evidence:

That "WARNING: sanitizing HTML stripped some content" message gives the game away.

But sometimes you know enough about the HTML you're getting back to trust it. You know it's not infected with XSS threats.

So you just want Angular to display the raw HTML as you got it.

In this guide, I'll show you how to do that with the aid of a custom pipe.

But First...

Before you do anything you read about in this guide, you must first talk to a data security consultant. 

That's because you're taking away a virtual security fence that prevents bad guys from screwing with your users.

Again, don't do anything I recommend here without first talking to a professional who understands modern-day data security best-practices. Let that person veto any suggestions I offer.

No exceptions.

Piping Hot

You're going to fix this problem with the aid of a Pipe.

Now what the heck is a Pipe in Angular?

In a nutshell, it's a way to transform data. I think it's safe to say that it's most frequently used to transform strings.

Angular itself offers built-in Pipes that you can use to manipulate data:

  • DatePipe
  • CurrencyPipe
  • DecimalPipe
  • PercentPipe

And others.

Unfortunately, none of the prefab Pipes will work for you here. So you're going to have to create your own.

Yeah. Angular lets you do that, too.

So create a new file in your favorite util directory. Call it nosanitizerpipe.ts. Make it look like this:

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

@Pipe({ name: 'noSanitize' })
export class NoSanitizePipe implements PipeTransform {
  constructor(private domSanitizer: DomSanitizer) { }

  transform(html: string): SafeHtml {
    return this.domSanitizer.bypassSecurityTrustHtml(html);
  }
}

That's easy enough. A couple of things to note here.

First, take a look at the name attribute in the @Pipe annotation. That's the name you'll use when you reference the Pipe in HTML.

Next, note that the code makes use of DomSanitizer. That's the class that Angular uses to protect you from insecure HTML.

But it's also the class that you can use to override Angular's default behavior.

And that's what you'll do here. Assuming you've talked with that data security consultant.

The DomSanitizer method bypassSecurityTrustHtml() is the override. When you use that method, you're telling Angular: "I trust this HTML. You don't need to sanitize. I know what I'm doing. I'm willing to take the risks. Please show everything."

And that's what will happen.

Into the Module

The next thing you need to know is that you must import that Pipe class into the module where you'll use it.

It's not good enough to import it at the component level. That won't work. Add it in the module.

Start by importing it:

import { NoSanitizePipe } from '../../util/nosanitizepipe';

Then declare it:

@NgModule({
  declarations: [
...
    NoSanitizePipe
  ]
...

Now you can use it in any component that's a part of that module.

Tempted to Use It in the Template?

And here's how you use it in the HTML:

<mat-card-content [innerHTML]="email.html | noSanitize"></mat-card-content>

Pay attention to the innerHTML binding property. The source there is email.html but you can see that it's piped (oddly enough, with the pipe character) with noSanitize. That's how you use it.

Now the UI will display all HTML. Totally unsanitized. Warts and everything.

Just make sure that's what you want before you go that route.

Wrapping It Up

Once more, with feeling: consult a data security expert before following any of these recommendations. Better safe than sorry.

But if your consultant gives you the all-clear, you'll display HTML just as you received it from any downstream microservices. And that's what you want, isn't it?

Have fun!

Photo by Karolina Grabowska from Pexels