Angularjs ng-bind-html-unsafe replacement
Asked Answered
J

4

10

I used to be able to use ng-bind-html-unsafe to output unsanitized code (because sanitization happens serverside).

But now that option is gone? I know I can use $sce.trustAsHtml but adding that to the JavaScript all over the place is a huge pain when unsafe was so easy to use.

How do I get unsafe back?

Jink answered 20/9, 2013 at 21:40 Comment(0)
V
18

Well, it's quite simple to just create your own directive, here is an example.

Directive:

app.directive('bindHtmlUnsafe', function( $compile ) {
    return function( $scope, $element, $attrs ) {

        var compile = function( newHTML ) { // Create re-useable compile function
            newHTML = $compile(newHTML)($scope); // Compile html
            $element.html('').append(newHTML); // Clear and append it
        };

        var htmlName = $attrs.bindHtmlUnsafe; // Get the name of the variable 
                                              // Where the HTML is stored

        $scope.$watch(htmlName, function( newHTML ) { // Watch for changes to 
                                                      // the HTML
            if(!newHTML) return;
            compile(newHTML);   // Compile it
        });

    };
});

Usage:

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

Demo: http://jsfiddle.net/cC5VZ/2

Vinasse answered 21/9, 2013 at 0:4 Comment(6)
Thanks! Why do you clear and append it instead of just setting it with .html()?Jink
Because if you use html(); it end's up like this [object HTMLHeadingElement] and I also prefer to append anywayVinasse
it doesn't for me. Appending it is slower AFAIK, I changed it to just use html()Jink
Seems kinda ridiculous they would remove useful functionality and force people to write their own directives for it.Swaggering
@Swaggering That's angular for you.Vinasse
@Swaggering Don't be hating. They improved security and made it harder for ignorant users to unknowingly compromise their apps. see here, all you need to do is use $sce.trustAsHtml(...) to explicitly trusted html.Timmy
T
23

Simpler again.

App.filter('unsafe', ['$sce', function ($sce) {
    return function (val) {
        return $sce.trustAsHtml(val);
    };
}]);

Usage:

<any ng-bind-html="content | unsafe"></any>

For more on html binding check the docs here.

Just a warning: make sure you actually trust the html, or you could be opening a hole in your sites security.

Timmy answered 24/2, 2014 at 4:50 Comment(4)
Worked fine with ng-bind-html but not with <p>{{ … }}</p> for me.Riggins
Thanks @HenrikN you are correct. {{ ... }} will only print out the text of the content. I have updated the answer.Timmy
@J-Dizzle That is pretty similar. I guess he got their first, though it is a pretty common and well known pattern. Thanks for the notice.Timmy
So simple. So elegant. So beautiful.Wolffish
V
18

Well, it's quite simple to just create your own directive, here is an example.

Directive:

app.directive('bindHtmlUnsafe', function( $compile ) {
    return function( $scope, $element, $attrs ) {

        var compile = function( newHTML ) { // Create re-useable compile function
            newHTML = $compile(newHTML)($scope); // Compile html
            $element.html('').append(newHTML); // Clear and append it
        };

        var htmlName = $attrs.bindHtmlUnsafe; // Get the name of the variable 
                                              // Where the HTML is stored

        $scope.$watch(htmlName, function( newHTML ) { // Watch for changes to 
                                                      // the HTML
            if(!newHTML) return;
            compile(newHTML);   // Compile it
        });

    };
});

Usage:

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

Demo: http://jsfiddle.net/cC5VZ/2

Vinasse answered 21/9, 2013 at 0:4 Comment(6)
Thanks! Why do you clear and append it instead of just setting it with .html()?Jink
Because if you use html(); it end's up like this [object HTMLHeadingElement] and I also prefer to append anywayVinasse
it doesn't for me. Appending it is slower AFAIK, I changed it to just use html()Jink
Seems kinda ridiculous they would remove useful functionality and force people to write their own directives for it.Swaggering
@Swaggering That's angular for you.Vinasse
@Swaggering Don't be hating. They improved security and made it harder for ignorant users to unknowingly compromise their apps. see here, all you need to do is use $sce.trustAsHtml(...) to explicitly trusted html.Timmy
C
1

Simplest way, without $sce:

module.directive('html', function() {
    function link(scope, element, attrs) {

        var update = function() {
            element.html(scope.html);
        }

        attrs.$observe('html', function(value) {
            update();
        });
    }

    return {
        link: link,
        scope:  {
            html:   '='
        }
    };
});

How to use:

<div html="angular.variable"></div>
Curdle answered 8/2, 2014 at 3:12 Comment(0)
A
0

I would strongly recommend checking out this SIMPLE JSFiddle example. Was a lifesaver:

http://jsfiddle.net/cC5VZ/2/

<div ng-app="ngBindHtmlExample">
  <div ng-controller="ngBindHtmlCtrl">
   <p ng-bind-html="myHTML" compile-template></p>
  </div>
</div>



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

app.controller('testApp', function( $scope ) {
    $scope.testHTML = '<h1> Welcome :) </h1>';
});

app.directive('bindHtmlUnsafe', function( $parse, $compile ) {
    return function( $scope, $element, $attrs ) {
        var compile = function( newHTML ) {
            newHTML = $compile(newHTML)($scope);
            $element.html('').append(newHTML);        
        };

        var htmlName = $attrs.bindHtmlUnsafe;

        $scope.$watch(htmlName, function( newHTML ) {
            if(!newHTML) return;
            compile(newHTML);
        });

    };
});
Amino answered 13/8, 2014 at 19:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.