Problems with forced escaping of characters when creating AngularJs element

68 views Asked by At

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

There are 1 answers

2
Viktar Tserashchuk On

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.