Escape or Sanitize HTML in Angular

By Dave Ceddia Comment

Want to render some user-provided data to the page, but for whatever reason, you can’t use Angular’s {{ curly brace syntax }}?

Maybe your first thought is to mash it together with a string, like this:

var content = "<span>" + userContent + "</span>";

But be careful! This kind of thing can open you up to XSS attacks and other nasty things.

You need to escape or sanitize that data before placing it on the page.


Angular automatically sanitizes data if you use the ng-bind-html directive. This means it strips out HTML entirely.

A string of Hello <em>World!</em> becomes Hello World.

Manually Sanitize

If you want to sanitize data without using ng-bind-html, you can use the $sanitize service. Install it and require the module as a dependency:

bower install angular-sanitize

angular.module('yourThing', ['ngSanitize', ...])

Then just inject it where needed, and use it:

function yourThing($sanitize) {
  return {
    function getContent(str) {
      return "<span>" + $sanitize(str) + "</span>";


Angular automatically escapes data if you use ng-bind or the {{ curly brace syntax }}. This means it outputs the literal characters instead of interpreting them as HTML.

Data that looks like Hello <em>World!</em> will render as Hello <em>World!</em> (not Hello World).

Manually Escape

Angular doesn’t seem to expose a built-in service for escaping. However Lodash (v3) has a _.escape function that does exactly this.

Install Lodash if you aren’t already using it: bower install lodash

Then escape your string as needed:

function yourThing() {
  return {
    function getContent(str) {
      return "<span>" + _.escape(str) + "</span>";

And with that, you and your users are safe for another day.

If you want my regularly-scheduled posts on best-practices Angular, as well as the all-new world of Angular 2, sign up for my newsletter below.

Thanks for reading!

For a step-by-step approach to learning React,
check out my book — grab 2 free sample chapters.

As far as I am concerned, even the intro which is free is worth the price.
— Isaac
comments powered by Disqus