228

ng-bind-html-unsafe was removed in Angular 1.2

I'm trying to implement something where I need to use ng-bind-html-unsafe. In the docs and on the github commit they say:

ng-bind-html provides ng-html-bind-unsafe like behavior (innerHTML's the result without sanitization) when bound to the result of $sce.trustAsHtml(string).

How do you do this?

Mark Coleman
  • 40,542
  • 9
  • 81
  • 101
timhaak
  • 2,403
  • 2
  • 14
  • 7
  • possible duplicate of [Insert HTML into view using AngularJS](http://stackoverflow.com/questions/9381926/insert-html-into-view-using-angularjs) – kontur Oct 03 '14 at 13:42

10 Answers10

639

Filter

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

Usage

<ANY ng-bind-html="value | unsafe"></ANY>
Alex
  • 7,639
  • 3
  • 45
  • 58
Chris
  • 12,192
  • 5
  • 21
  • 23
  • 1
    Why do you need `ngSanitize` here? –  Jan 07 '14 at 12:30
  • 2
    @OliverJosephAsh because the $sce service is defined in ngSanitize. they broke apart major functionality so we can use angular just a little bit and not always have to use the entire framework. – Chris Sattinger Jan 10 '14 at 09:17
  • 1
    I've been wondering what the security implications of something like this might be? I've asked for more clarification in [a separate question](http://stackoverflow.com/questions/21144546/angular-sce-vs-html-in-external-locale-files). All input appreciated! – Philip Bulley Jan 15 '14 at 17:44
  • 9
    @felix in version 1.2 (when they added this) it is enabled by default as part of core, not `ngSanitize`, so there is no need for `ngSanitize` – TheSharpieOne Jan 15 '14 at 19:14
  • 1
    How is app.filter called here - would like some underlying understanding of what is going on. I can see that we might call the function app.filter(value to be cleaned); but is angular doing this behind the scenes with your Usage example ? Thanks – landed Mar 06 '14 at 15:44
  • 1
    Ahh I see that filter is specified in this case 'unsafe' and it runs the function. Does anyone know of a good tutorial for this kind of understanding on what this function is doing. Ok so I can say that the function returns another function I cant see why not just run the line of code why wrap it in another function. And I cant see how val is mapped. – landed Mar 06 '14 at 16:00
  • 2
    This is a design decision made by the angular team - that's how filters should be implemented - if you do it otherwise, they won't work. The reason why this must return a function is that angular can delay processing until it 'finds the right moment'. Otherwise the framework would not have any influence on when the filter is called. That's both good and bad, but as far as I can tell - it's necessary to cope with angulars' tricky processing. More info here: http://docs.angularjs.org/api/ng/provider/$filterProvider – Chris Mar 06 '14 at 20:37
  • I found that I was not able to inject html into a directive that for me is a modal dialogue So the following didnt work !
    So I wanted to reuse the modal by injecting the content depending - sounds reasonable. I am still searching for an elegant modal solution in angular that can handle programatic content swap.
    – landed Mar 15 '14 at 11:51
  • is it possible to use it with input along with ngmodel – Srihari Goud Jun 13 '14 at 13:48
  • 1
    No need to wrap `$sce.trustAsHtml` in an extra function. You can just `return $sce.trustAsHtml` and save two lines. – Daniel Darabos Sep 10 '14 at 14:30
  • I tried this solution with my custom tag. It seems automatically lost its directive logic and styling for some reason. Any idea why this may be? – Sani Yusuf Jan 08 '15 at 11:33
  • There is no need of `$sce.trustAsHtml`. Just ng-bind-html works perfectly! – RN Kushwaha Feb 28 '15 at 10:15
  • 1
    This is really practical as it avoids polluting your controllers with $sce.trusAsHtml – Tiagojdferreira Dec 31 '15 at 11:11
  • Since I don't work with Angular often, this would've taken me a while to figure out myself. Thanks a lot, enjoy the bounty. – Etheryte Jan 05 '16 at 06:28
  • How to do this for summernote editor, initially i will get the json data(which contains html) from server, in summernote i am using ng-model. how to make the code as trusted to display in summernote editor – codelearner Jun 09 '16 at 04:20
  • 1
    just to make the filter minfication safe app.filter('unsafe'['$sce', function($sce) { return $sce.trustAsHtml; }]); – rahul rathore Feb 16 '17 at 13:45
256

That should be:

<div ng-bind-html="trustedHtml"></div>

plus in your controller:

$scope.html = '<ul><li>render me please</li></ul>';
$scope.trustedHtml = $sce.trustAsHtml($scope.html);

instead of old syntax, where you could reference $scope.html variable directly:

<div ng-bind-html-unsafe="html"></div>

As several commenters pointed out, $sce has to be injected in the controller, otherwise you will get $sce undefined error.

 var myApp = angular.module('myApp',[]);

 myApp.controller('MyController', ['$sce', function($sce) {
    // ... [your code]
 }]);
Nenad
  • 24,809
  • 11
  • 75
  • 93
  • 10
    How can you do this with a value returned by a function?

    {{description(category.id)}}

    – dasper Sep 20 '13 at 07:00
  • 2
    Not sure if I got you right, but: `

    ` and `$scope.trustedHtml = $sce.trustAsHtml(description(category.id));`
    – Nenad Sep 20 '13 at 17:55
  • 1
    I love you for responding! Apparently the issue was me using 1.0.8. I have a form with dynamic number of sections so on change I wanted to show the proper description. `

    ` then the last line of the function: `return $sce.trustAsHtml(value);`
    – dasper Sep 20 '13 at 18:49
  • 2
    But... var x = sce.trustAsHtml('foo'); var y = sce.trustAsHtml('foo'); x==y; false ... So shouldn't this create an infinite digest loop since your function returns a new object ? – rych Oct 01 '13 at 20:06
  • 1
    To answer my own comment, this was fixed in master: https://github.com/angular/angular.js/pull/4087 Angular (as of today, anyway) compares the toString value, not the object reference. – rych Oct 01 '13 at 20:24
  • 1
    Just a notice: there is non need to declare html and trustedHtml apart, is simply a matter of marking the data using $sce.trustAsHtml(), so is simple as declaring: $scope.html = $sce.trustAsHtml(theHTML)… anyway, thank you! – daveoncode Nov 17 '13 at 15:25
  • 25
    Also worth mentioning is $sce needs to be passed into the controller or you get $sce is not defined – isimmons Dec 21 '13 at 23:41
  • @Nenad, can scope variables be used here `$sce.trustAsHtml($scope.html <--inside html, that is marked as trusted);` – Eugene Jul 02 '14 at 09:02
  • 1
    make sure to add dependency on ngSanitize to your module. – Kildareflare Mar 11 '15 at 02:31
  • `ng-bind-html-unsafe` is deprecated. – mpgn Oct 17 '15 at 14:48
  • how can i use this in an array of strings .... http://stackoverflow.com/questions/36299635/apply-strong-tags-to-a-string-in-my-js-coffee-file – Serge Pedroza Mar 30 '16 at 20:50
  • How to do this for summernote editor, initially i will get the json data(which contains html) from server, in summernote i am using ng-model. how to make the code as trusted to display in summernote editor – codelearner Jun 09 '16 at 04:19
  • @Abaij I added additional description in the answer. You have to inject `$sce` in the controller. – Nenad Aug 04 '16 at 09:07
  • 1
    Don't you need a comma before the first square bracket? `'MyController, '['$sce', function($sce) ` – Jonathan Mar 17 '17 at 10:26
  • Left insert sanitize – elciospy Feb 02 '18 at 18:27
  • Or make one line in your controller: `$scope.trustedHtml = $sce.trustAsHtml('
    • render me please
    ');`
    – Steffo Dimfelt May 25 '18 at 09:14
  • @hawkeye That would be incorrect code. You want to attach `trustedHtml` to the `$scope`, so it's exposed in the template HTML markup. – Nenad Sep 07 '18 at 13:22
16

Personally I sanitize all my data with some PHP libraries before going into the database so there's no need for another XSS filter for me.

From AngularJS 1.0.8

directives.directive('ngBindHtmlUnsafe', [function() {
    return function(scope, element, attr) {
        element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);
        scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {
            element.html(value || '');
        });
    }
}]);

To use:

<div ng-bind-html-unsafe="group.description"></div>

To disable $sce:

app.config(['$sceProvider', function($sceProvider) {
    $sceProvider.enabled(false);
}]);
Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
Michael J. Calkins
  • 32,082
  • 15
  • 62
  • 91
  • I am unclear what the difference is between the two examples. One of our team members has a problem where they have System.out.println(“Hello World!”); in the database. She is using
    and it appears on the page as: System.out.println(“Hello World!”);. Are you saying that using your ngBindHtmlUnsafe directive would fix this problem?
    – Alan2 Oct 13 '13 at 14:58
  • @Alan I believe it would work if it was ``, haven't tried this personally because my PHP removed all JS from user input. I removed my second example because Angular's native one is superior in every way just use that one. – Michael J. Calkins Oct 13 '13 at 16:38
  • How to do this for summernote editor, initially i will get the json data(which contains html) from server, in summernote i am using ng-model. how to make the code as trusted to display in summernote editor – codelearner Jun 09 '16 at 04:19
9

var line = "<label onclick="alert(1)">aaa</label>";

1. use filter

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

using (html):

<span ng-bind-html="line | unsafe"></span>
==>click `aaa` show alert box

2. use ngSanitize : safer

include angular-sanitize.js

<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>

add ngSanitize in root angular app

var app = angular.module("app", ["ngSanitize"]);

using (html):

<span ng-bind-html="line"></span>
==>click `aaa` nothing happen
nguyên
  • 5,156
  • 5
  • 43
  • 45
  • How to do this for summernote editor, initially i will get the json data(which contains html) from server, in summernote i am using ng-model. how to make the code as trusted to display in summernote editor – codelearner Jun 09 '16 at 04:19
7

Simply creating a filter will do the trick. (Answered for Angular 1.6)

.filter('trustHtml', [
        '$sce',
        function($sce) {
            return function(value) {
                return $sce.trustAs('html', value);
            }
        }
    ]);

And use this as follow in the html.

<h2 ng-bind-html="someScopeValue | trustHtml"></h2>
STEEL
  • 8,955
  • 9
  • 67
  • 89
3

If you want the old directive back, you can add this to your app:

Directive:

directives.directive('ngBindHtmlUnsafe', ['$sce', function($sce){
    return {
        scope: {
            ngBindHtmlUnsafe: '=',
        },
        template: "<div ng-bind-html='trustedHtml'></div>",
        link: function($scope, iElm, iAttrs, controller) {
            $scope.updateView = function() {
                $scope.trustedHtml = $sce.trustAsHtml($scope.ngBindHtmlUnsafe);
            }

            $scope.$watch('ngBindHtmlUnsafe', function(newVal, oldVal) {
                $scope.updateView(newVal);
            });
        }
    };
}]);

Usage

<div ng-bind-html-unsafe="group.description"></div>

Source - https://github.com/angular-ui/bootstrap/issues/813

Adrian Enriquez
  • 8,175
  • 7
  • 45
  • 64
  • Does not behave the same. – Casey Dec 19 '14 at 19:24
  • How to do this for summernote editor, initially i will get the json data(which contains html) from server, in summernote i am using ng-model. how to make the code as trusted to display in summernote editor – codelearner Jun 09 '16 at 04:20
3

JavaScript

$scope.get_pre = function(x) {
    return $sce.trustAsHtml(x);
};

HTML

<pre ng-bind-html="get_pre(html)"></pre>
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
wcc526
  • 3,915
  • 2
  • 31
  • 29
  • How to do this for summernote editor, initially i will get the json data(which contains html) from server, in summernote i am using ng-model. how to make the code as trusted to display in summernote editor – codelearner Jun 09 '16 at 04:19
1

For Rails (at least in my case) if you are using the angularjs-rails gem, please remember to add the sanitize module

//= require angular
//= require angular-sanitize

And then load it up in your app...

var myDummyApp = angular.module('myDummyApp', ['ngSanitize']);

Then you can do the following:

On the template:

%span{"ng-bind-html"=>"phone_with_break(x)"}

And eventually:

$scope.phone_with_break = function (x) {
  if (x.phone != "") {
   return x.phone + "<br>";
  }
  return '';
}
SomeDudeSomewhere
  • 3,928
  • 1
  • 23
  • 27
  • How to do this for summernote editor, initially i will get the json data(which contains html) from server, in summernote i am using ng-model. how to make the code as trusted to display in summernote editor – codelearner Jun 09 '16 at 04:20
  • Check this out: https://github.com/summernote/summernote/issues/59#issuecomment-29517163 – SomeDudeSomewhere Jun 09 '16 at 15:58
0
my helpful code for others(just one aspx to do text area post)::

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication45.WebForm1" %>

<!DOCTYPE html>

    enter code here

<html ng-app="htmldoc" xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="angular.min.js"></script>
    <script src="angular-sanitize.min.js"></script>
    <script>
        angular.module('htmldoc', ['ngSanitize']).controller('x', function ($scope, $sce) {
            //$scope.htmlContent = '<script> (function () { location = \"http://moneycontrol.com\"; } )()<\/script> In last valid content';
            $scope.htmlContent = '';
            $scope.withoutSanitize = function () {
                return $sce.getTrustedHtml($scope.htmlContent);
            };
            $scope.postMessage = function () {
                var ValidContent = $sce.trustAsHtml($scope.htmlContent);

                //your ajax call here
            };
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
        Example to show posting valid content to server with two way binding
        <div ng-controller="x">
            <p ng-bind-html="htmlContent"></p>
            <textarea ng-model="htmlContent" ng-trim="false"></textarea>
            <button ng-click="postMessage()">Send</button>
        </div>
    </form>
</body>
</html>
Saurabh
  • 1,545
  • 1
  • 9
  • 9
0
$scope.trustAsHtml=function(scope)
{
    return $sce.trustAsHtml(scope);
}
<p class="card-text w-100" ng-bind-html="trustAsHtml(note.redoq_csd_product_lead_note)"></p>
  • 3
    Please don't post only code as an answer, but also include an explanation what your code does and how it solves the problem of the question. Answers with an explanation are generally of higher quality, and are more likely to attract upvotes. – Mark Rotteveel Oct 27 '19 at 06:43