0

I stumbled upon an issue with AngularJS and creation of elements. In short: I need to create an element with html contents, but I do want to have the reference to that element at hand, so that I can perform some actions on it without actually rendering it in the browser.

I tried doing the following:

var template = angular.element('<div>' + templateString + '</div>');
$compile(template)($scope);

which kinda does the trick, but... Some of these templates have logical expression in them. in example:

<div ng-if="a && b">something</div>

Unfortunately it seems that when I try to create such an element, regardless if I use $sce.trustAsHtml() with ng-bind-html or not the & characters within these conditions get escaped as &amp;. The html I get in the template looks like this:

<div ng-if="a &amp;&amp; b">something</div>

Please take a look at the fiddle: https://jsfiddle.net/3uxdrp7b/1/

if this is a known issue - I'd be thankful for pointing me in the right direction, cause I've been banging my head against this for quite some time and I can't get it to work. Every example I looked at had a simple html inside the binding - it all works ok unless I use the cursed &.

1 Answers1

0

The main issue is that the element is not updated right after compiling. It will contain the correct value after the current digest cycle is finished.

<!-- HTML -->
<div class="container" ng-app="app" ng-controller="DemoController">
  <h3>Result:</h3> <span ng-bind-html="el"></span>
</div>

// js
var app = angular.module("app", ["ngSanitize"]);
app.controller("DemoController", ["$scope", "$compile", "$timeout",
    function($scope, $compile, $timeout) {
    $scope.a = true;
    $scope.b = true;
    let contents = "<div ng-if='a && b'>something</div>";
    let compiled = $compile("<div>" + contents + "</div>")($scope);

    $timeout(function(){
      console.log(compiled.html());
      $scope.el = compiled.html();
    },0,true);
  }]);

The fiddle: https://jsfiddle.net/vy9svmop/

It might be that in your case it is simpler to use the $interpolate service to recive the immediate result.

  • I use it outside of a digest cycle, so add $scope.$digest to achieve what you've stated. However it does not fix the issue - it works in your fiddle because you use the `ng-bind-html` inside your view. If you were to display the html contents they still contain the `&` chars. (https://jsfiddle.net/4avuh37d/1/). What I need is for this html not to have them in the first place. – Michal Lozinski Oct 25 '17 at 06:20
  • This is not angular, this is the browser. .html(), innerHTML, ... are return the html string that is generated by the browser based on the DOM element. There is no way to receive the original html with DOM element. The fiddle from the answer put the extracted html to the browser console. The & is here as well. Angular does not put it there. The browser serializes the elment in string that way. So, you can either use ng-bind-html to render this fragment as html or render the original html string or write code to replace & symbols in the string. – Viktar Tserashchuk Oct 25 '17 at 08:11