Rendering HTML with angular

by Dan Atkinson

HTML

<h2>Rendering HTML with angularJS</h2>
<div ng-app="angularApp" ng-controller="appController">
    This input field is ng-model bound to $scope.content:<br />
    <textarea cols="90" ng-model="content" rows="5"></textarea><br /><br />  
    
    <b class="heading" ng-non-bindable>{{content}}</b><br />
    {{content}}<br /><br />
    
    <b class="heading">&lt;div ng-bind-html="content"&gt;&lt;/div&gt;</b>
    <span style="color: red"><pre>Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context.</pre></span>
    <div ng-bind-html="content"></div>
    <div class="info">if you look in the console.log, you'll see a messages saying couldn't render unsafe html.  
        This is because you didn't explicitly mark the html as safe using the $sce.trustAsHtml function</div><br /><br />
    
    <b class="heading">&lt;div ng-bind-html="getHtml(content)"&gt;&lt;/div&gt;</b><br />
    <div ng-bind-html="getHtml(content)"></div><br />
    <div class="info">In the controller, getHTML uses the $sce.trustAsHtml() function to mark the html 
        as "safe" for binding. This works because you're explicitly binding to html content 
        (with ng-bind-html) <em>and</em> indicating that the html you are binding to is safe to 
        render</div><br /><br />
    
    <b class="heading">&lt;div ng-bind-html="content | html"&gt;&lt;/div&gt;</b><br />
    <div ng-bind-html="content | html"></div><br />
    <div class="info">This works for the same reason marked above but is globally accessible throughout your
    angular application instead of being defined in a specific controller.</div><br /><br />    
    
    <b class="heading" ng-non-bindable>{{content | html}}</b><br />
    {{content | html}}<br /><br />
    <div class="info">This doesn't work because <pre ng-non-bindable>{{content}}</pre> uses ng-bind 
        (which reads the text of an element), not ng-bind-html (which reads the html of an element), so even
        though it's marked "safe", it's not...

CSS

body{
    font-family: verdana;
    font-size: 10pt;
}
.info{
    padding-left: 10px;
    border-left: solid 3px #ccc;
    margin-top: 5px;
}
.heading{
    border-bottom: solid 1px #ccc;
    display: block;
    padding-top: 10px;
}

JavaScript

var app = angular.module("angularApp", []);
app.controller("appController", function($scope, $sce){
    $scope.content = "This text is <em>html capable</em> meaning you can have <a href=\"#\">all</a> sorts <b>of</b> html in here.";
    $scope.getHtml = function(html){
        return $sce.trustAsHtml(html);
    };
});

app.filter('html', function($sce) {
    return function(val) {
        return $sce.trustAsHtml(val);
    };
});