Programmatically compile an Angular template into an HTML string

In my Angular 1.5.11 application, I am trying to programmatically compile a template and get the result as an HTML string. Template Content

<div ng-if="foo">
  <div>foo is {{foo}}, bar is {{bar}}</div>
</div> 

My attempt to compile it into an HTML string:

app.controller('MainCtrl', function($scope, $rootScope, $compile) {

  function compileHtmlTemplate (templateContent, model) {
    var templateScope = $rootScope.$new(true);
    angular.extend(templateScope, model);

    return $compile(templateContent)(templateScope);
  }

  var templateContent = $('#template').html();
  var model = {foo: 'fooValue', bar: 'barValue'};
  var compiledHtml = compileHtmlTemplate(templateContent, model);
  var htmlAsString = $('<div></div>').html(compiledHtml).html();

  $scope.result = htmlAsString;
});

However, as you can see in this Plunker example , it does not work. I need to compile a template, not just interpolate it, because it contains a directive ng-if.

+4
source share
4 answers

The angular digest loop should end before you access the value. You can achieve this using $timeout.

$templateCache , .

var app = angular.module('plunker', ['ngSanitize']);

app.controller('MainCtrl', function($scope, $rootScope, $compile, $timeout, $templateCache) {

  function compileHtmlTemplate (templateContent, model) {
    var templateScope = $rootScope.$new(true);
    angular.extend(templateScope, model);

    var compiled = $compile(templateContent)(templateScope);

    var parent = $("<div>").html(compiled);

    console.log("Won't work! Digest hasn't finished:", parent[0].innerHTML);

    $timeout(function(){ // must wait till Angular has finished digest
      console.log('Will work, digest has now completed:', parent[0].innerHTML);

      $scope.result = parent[0].innerHTML;
    }, 0);
  }

  // either do something with the compiled value within the $timeout, or watch for it
  $scope.$watch('result', function(newValue, oldValue) {
      if (newValue !== undefined) {
        console.log("Do something in the $timeout or here... " + newValue);
      }
  });

  // you can access the template via the template cache if you wanted
  var templateContent = $templateCache.get('template');
  var model = {foo: 'fooValue', bar: 'barValue'};
  var compiledHtml = compileHtmlTemplate(templateContent, model);
});

Plunker: https://plnkr.co/edit/ajC3Iqkxpi6O9gfieHeR?p=preview

+2

, $, .

var app = angular.module('plunker', ['ngSanitize']);

app.controller('MainCtrl', function($scope, $rootScope, $compile, $interpolate) {

  function compileHtmlTemplate (templateContent, model) {
    var templateScope = $rootScope.$new(true);
    angular.extend(templateScope, model);

    var tpl = $compile(templateContent)(templateScope);
    console.log(tpl);

    return $interpolate(tpl.html(),model)
  }

  var templateContent = $('#template').html();

  var model = {foo: 'fooValue', bar: 'barValue'};
  var compiledHtml =compileHtmlTemplate(templateContent)(model);
  //console.log(compiledHtml)
  var htmlAsString = $('<div></div>').html(compiledHtml).html();

  $scope.result = htmlAsString;
});

html , .

$compile , html

https://plnkr.co/edit/TPvOXb5TWHGUunBMFubF?p=preview

0

HTML, {{}}, ng-bind-html $sanitaze angular

https://plnkr.co/edit/GwM5CEemo961s2CeUsdA?p=preview

var compiledHtml = compileHtmlTemplate(templateContent, model);
var element = angular.element('<div></div>').html(compiledHtml)
$timeout(function() {
  $scope.result = element.html()
})

- ngIf compiledHtml ngIf, , , , , , compiledHtml html $timeout , $digest. ,

0

- ( , angular)

  var templateContent = $templateCache.get("template");
  //var templateContent = $('#template').html();
  //comment: get html in angular way, not using jquery

  var model = {foo: 'fooValue', bar: 'barValue'};
  var templateScope = $rootScope.$new(true);
  templateScope = angular.extend(templateScope, model);
  //angular.extend(templateScope, model);
  //comment: make sure to capture result of angular.extend

  var compiledElement = $compile(templateContent)(templateScope);
  //var compiledHtml = $compile(templateContent)(templateScope);
  //comment: result of compilation is not an html but an angular element

  var targetElement = angular.element("#result");
  //var htmlAsString = $('<div></div>').html(compiledHtml).html();
  //comment: find the element using angular and not jquery


  targetElement.append(compiledElement);
  //$scope.result = htmlAsString;
  //comment: don't just assign string, append an angular element

plunker

html

  replaced
  <div>{{result}}</div>

  with
  <div id="result"></div>
0

Source: https://habr.com/ru/post/1674297/


All Articles