Squrler
Squrler

Reputation: 3514

Angular: ng-bind-html filters out ng-click?

I have some html data that I'm loading in from a json file.

I am displaying this html data by using ngSanitize in my app and using ng-bind-html.

Now I would like to convert any links in the json blob from the standard

to:

So I'm doing some regExp on the json file to convert the links, but for some reason however ng-bind-html is filtering out the ng-click in it's output, and I can't figure out why. Is it supposed to do this, and if so is it possible to disable this behavior?

Check out this jsFiddle for a demonstration: http://jsfiddle.net/7k8xJ/1/

Any ideas?

Upvotes: 33

Views: 30748

Answers (3)

Satys
Satys

Reputation: 2425

I still faced some issue with the compile, as that was not fulfilling my requirement. So, there is this, a really nice and easy hack to work around this problem.

We replace the ng-click with onClick as onClick works. Then we write a javascript function and call that on onClick event. In the onClick function, we find the scope of the anchor tag and call that required function explicitly.

Below is how its done :)

Earlier,

<a id="myAnchor" ng-click="myControllerFunction()" href="something">

Now,

<a id="myAnchor" onClick="tempFunction()" href="something">

at the bottom or somewhere,

<script>
function tempFunction() {
 var scope = angular.element(document.getElementById('myAnchor')).scope();
  scope.$apply(function() {
    scope.myControllerFunction();
 });
}
</script>

This should work now. Hope that helps someone :)

For more info, see here.

Upvotes: 3

dave
dave

Reputation: 64657

Ok, so the issue is that it isn't compiling the html you include (angular isn't parsing it to find directives and whatnot). Can't think of a way to make it to compile from within the controller, but you could create a directive that includes the content, and compiles it.

So you would change

<p ng-bind-html="name"></p>

to

<p compile="name"></p>

And then for the js:

var myApp = angular.module('myApp', ['ngSanitize']);
angular.module('myApp')
.directive('compile', ['$compile', function ($compile) {
  return function(scope, element, attrs) {
    scope.$watch(
      function(scope) {
        return scope.$eval(attrs.compile);
      },
      function(value) {
        element.html(value);
        $compile(element.contents())(scope);
      }
   )};
  }]).controller('MyCtrl', function($scope) {
    var str = 'hello http://www.cnn.com';
    var urlRegEx = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-]*)?\??(?:[\-\+=&;%@\.\w]*)#?(?:[\.\!\/\\\w]*))?)/g;
    result = str.replace(urlRegEx, "<a ng-click=\"GotoLink('$1',\'_system\')\">$1</a>");
    $scope.GotoLink = function() { alert(); }
    $scope.name = result;
});

Angular 1.2.12: http://jsfiddle.net/7k8xJ/4/

Angular 1.4.3: http://jsfiddle.net/5g6z58yy/ (same code as before, but some people were saying it doesn't work on 1.4.*)

Upvotes: 49

user5740953
user5740953

Reputation: 179

Explicitly Trusting HTML With $sce When you want Angular to render model data as HTML with no questions asked, the $sce service is what you’ll need. $sce is the Strict Contextual Escaping service – a fancy name for a service that can wrap an HTML string with an object that tells the rest of Angular the HTML is trusted to render anywhere.

In the following version of the controller, the code asks for the $sce service and uses the service to transform the array of links into an array of trusted HTML objects using $sce.trustAsHtml.

app.controller('XYZController', function ($scope, $sce) {

$sce.trustAsHtml("<table><tr><td><a onclick='DeleteTaskType();' href='#workplan'>Delete</a></td></tr></table>");

Upvotes: 2

Related Questions