33

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

  • <a href="some_link">link</a>

to:

  • <a ng-click="GotoLink('some_link','_system')">link</a>.

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?

3
  • 1
    Does ng-bind-html-unsafe work? Commented Mar 29, 2014 at 22:58
  • Nope.. Then there is no output at all. Commented Mar 29, 2014 at 23:01
  • possible duplicate of angular ng-bind-html-unsafe and directive within it Commented Aug 21, 2015 at 15:34

3 Answers 3

49

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.*)

Sign up to request clarification or add additional context in comments.

4 Comments

This works great, thanks! Just as a thought (and I'm not really clear on if I'm understanding $sce correctly, documentation is a bit unclear) but isn't is possible to whitelist browse-to so it will get outputted by ng-bind-html?
This is not working for me in angular 1.4.3 throwing errors "Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!"
saw this solution in other answer as well.. but didn't work for me at 1.4.*
if this doesnt work for you, check that the method you want to call is indeed on your scope, depending on the scoping rules for the directive, it may be on the parents
3

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.

5 Comments

no, this is definitely not the way to do it, not testable, is a nasty workaround
calm down bro, i could do it this way, how can you not test it, didn't i mentioned above it as workaround? calm down bro, and if possible please remove your rage of downvote?
@Satys upvoted you back because you did mention it was a workaround
@KuraiBankusu Thank you
@LucaTrazzi walkarounds are usually nasty.
2

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>"); 

2 Comments

Attaching onclick handler is not same as attaching ng-click handler to an element. This will not work, when you'll use ng-click instead of onclick in your snippet.
@MNIslamShihan so how will you handle with ng-click with using $sce ?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.