在我的Angular 1.5.11应用程序中,我尝试以编程方式编译模板并将结果作为HTML字符串获取。模板的内容是
<div ng-if="foo">
<div>foo is {{foo}}, bar is {{bar}}</div>
</div>
我尝试将其编译为HTML字符串:
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;
});
但是,正如您在Plunker example中看到的那样,它无法正常工作。我需要编译模板而不是仅仅插入模板,因为它包含ng-if
指令。
答案 0 :(得分:2)
Angular的摘要周期需要在您访问该值之前完成。您可以使用$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
答案 1 :(得分:0)
是的,你可以在这里使用$ interpolate
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字符串
答案 2 :(得分:0)
如果您想要显示HTML,则无法使用{{}}
,您需要使用ng-bind-html
或使用$sanitaze
角度服务
我已经更新了您的plunker 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
到新创建的元素并在$timeout
中检索html而没有指定时间,因为它将在追加和$digest
周期后发生。希望有所帮助
答案 3 :(得分:0)
下面是您的代码的工作版本(大多数更改都与以角度方式执行相关)
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
html的一个小变化是
replaced
<div>{{result}}</div>
with
<div id="result"></div>