Angular ng-bind-html and the directive inside it

Plunker link

I have an element that I would like to associate with html.

<div ng-bind-html="details" upper></div>

It works. Now, along with this, I also have a directive that is bound to the associated html:

$scope.details = 'Success! <a href="#/details/12" upper>details</a>'

But the upper directive with div and anchor does not evaluate. How can I make it work?

+84
angularjs angularjs-directive
Jul 02 '13 at 4:48
source share
6 answers

I also had to deal with this problem, and after hours of searching the internet, I read @Chandermani's comment, which turned out to be the solution. You need to call the "compilation" directive using this template:

HTML:

 <div compile="details"></div> 

JS:

 .directive('compile', ['$compile', function ($compile) { return function(scope, element, attrs) { scope.$watch( function(scope) { // watch the 'compile' expression for changes return scope.$eval(attrs.compile); }, function(value) { // when the 'compile' expression changes // assign it into the current DOM element.html(value); // compile the new DOM and link it to the current // scope. // NOTE: we only compile .childNodes so that // we don't get into infinite loop compiling ourselves $compile(element.contents())(scope); } ); }; }]) 

Here you can see the worker.

+160
Jul 02 '13 at 13:14
source share

Thanks for the excellent vkammerer answer. One optimization I would recommend is not to look after compilation. $ Eval in terms of hours can have performance implications.

  angular.module('vkApp') .directive('compile', ['$compile', function ($compile) { return function(scope, element, attrs) { var ensureCompileRunsOnce = scope.$watch( function(scope) { // watch the 'compile' expression for changes return scope.$eval(attrs.compile); }, function(value) { // when the 'compile' expression changes // assign it into the current DOM element.html(value); // compile the new DOM and link it to the current // scope. // NOTE: we only compile .childNodes so that // we don't get into infinite loop compiling ourselves $compile(element.contents())(scope); // Use un-watch feature to ensure compilation happens only once. ensureCompileRunsOnce(); } ); }; }]); 

Here is a fork and an updated violin.

+31
Dec 06 '13 at 17:57
source share

Add this angular-bind-html-compile directive

 .directive('bindHtmlCompile', ['$compile', function ($compile) { return { restrict: 'A', link: function (scope, element, attrs) { scope.$watch(function () { return scope.$eval(attrs.bindHtmlCompile); }, function (value) { // Incase value is a TrustedValueHolderType, sometimes it // needs to be explicitly called into a string in order to // get the HTML string. element.html(value && value.toString()); // If scope is provided use it, otherwise use parent scope var compileScope = scope; if (attrs.bindHtmlScope) { compileScope = scope.$eval(attrs.bindHtmlScope); } $compile(element.contents())(compileScope); }); } }; }]); 

Use it like this:

 <div bind-html-compile="data.content"></div> 

Really easy :)

+22
Aug 07 '15 at 14:28
source share

Unfortunately, I do not have enough reputation for comment.

I could not get this to work for ages. I changed the ng-bind-html code to use this custom directive, but I was not able to remove the $scope.html = $sce.trustAsHtml($scope.html) that was necessary for ng-bind-html to work. As soon as I removed this, the compilation function began to work.

+13
Jul 23 '14 at 12:04 on
source share

For those dealing with content that has already passed through $sce.trustAsHtml , here's what I had to do differently

 function(scope, element, attrs) { var ensureCompileRunsOnce = scope.$watch(function(scope) { return $sce.parseAsHtml(attrs.compile)(scope); }, function(value) { // when the parsed expression changes assign it into the current DOM element.html(value); // compile the new DOM and link it to the current scope. $compile(element.contents())(scope); // Use un-watch feature to ensure compilation happens only once. ensureCompileRunsOnce(); }); } 

This is only part of the link directive since I am using a different layout. You will need to enter the $sce service as well as $compile .

+6
Jan 08 '15 at 15:22
source share

The best solution that I have found! I copied it and worked exactly as I needed. Thank you thank you thank you...

in the function of the directory link i have

 app.directive('element',function($compile){ . . var addXml = function(){ var el = $compile('<xml-definitions definitions="definitions" />')($scope); $scope.renderingElement = el.html(); } . . 

and in the directive template:

 <span compile="renderingElement"></span> 
-2
Mar 20 '14 at 13:37
source share



All Articles