ng-bind-html strips elements attributes


I'm trying to interpolate a string that contains some markup in a template.

In the controller:
$scope.message = "Hello moto <a ui-sref='home.test'>click</a>";


<div ng-bind-html="message.text"></div>

which renders as:

<div ng-bind-html="message.text" <div="" class="ng-binding">Hello moto <a>click</a></div>

Trying to use the following filter does not help either; the text is simpy escaped for either of the commented choices:

angular.module('test-filters', ['ngSanitize'])
    .filter('safe', function($sce) {
            return function(val) {
                return $sce.trustAsHtml(val);
                //return $sce.trustAsUrl(val);
                //return $sce.trustAsResourceUrl(val);

How can I interpolate my string without escaping it nor stripping attributes?

Edit: Plunker (updated with sylwester's version that has reference to ngSanitize

Problem courtesy of: rxdazn


Let have a look here it is sorted now. It didn't work because there was another directive inside a tag 'ui-sref', so you have to use $sce service.

in your js please add method:

 $scope.to_trusted = function(html_code) {
    return $sce.trustAsHtml(html_code);

and in view :

<p ng-bind-html="to_trusted(message)"></p>
Solution courtesy of: sylwester


In scenario where you are using ui.router path you must need to use $compile in combination with $sce for your dynamic html so that ui-sref work properly. If you don't do that you'll just see a Link which actually do not work.

e.g <span> Hello moto <a ui-sref='home.test'> Link </a> </span>

//You must need to add boundary conditions, this is just for demonstration
$scope.to_trusted = function(someHTML) {
    var compiledVal = $compile(someHTML)($scope);
    var compiledHTML = compiledVal[0].outerHTML;
    return $sce.trustAsHtml(compiledHTML);

And you use like this,

<p ng-bind-html="to_trusted(message)"></p>

Note that your message has to be a valid HTML starting from "<" so if you pass a non HTML to $compile you'll get jqlite error. I used <span> to handle your case.

Discussion courtesy of: Ahsan.Amin

You missed reference to angular-sanitize.js and you have inject it as well to

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

the simplest option in to bind html is ng-bind-html :

<li>link ng-html-bind <div ng-bind-html="message"></div></li>

please see Plunkr

Discussion courtesy of: sylwester

This recipe can be found in it's original form on Stack Over Flow.