我正在将AngularJs-UI组件用于Bootstrap。我想将填充的模板插入到弹出功能的数据元素之一中。这适用于所有不在ng-repeat内的元素。如何使ng-repeat元素在插值模板内工作?
我在http://plnkr.co/edit/Cuku7qaUTL1lxRkafKzv处有一个插件,它不起作用,因为我不知道如何在插件中获取Angular-UI-bootstrap。
<div data-popover="{{createHTML()}}">some content</div>
我的本地作用域具有
createHTML()
函数,看起来像这样。angular.module('myApp', ['ngSanitize'])
.controller("myController", function(myService){
$scope.createHTML = function() {
var thingy = { blah: "foobar", collection: [ "1", "2", "3" ] };
return myService.html_for(thingy);
}
});
服务是
angular.module('myApp')
.service('myService', function($templateCache, $interpolate, $sanitize, $log) {
"use strict";
function html_for(thingy) {
var template = $templateCache.get('thingyTemplate.html'),
link = $interpolate(template),
html = link(thingy),
unsafe = $sanitize(html);
return unsafe;
}
return {
html_for: html_for
}
});
范本:
<script type="text/ng-template" id="thingyTemplate.html">
<div>
<div><strong>Blah:</strong> {{blah}}</div>
<div data-ng-repeat="foo in collection"><strong>Collection:</strong> {{foo}}</div>
<div><strong>Collection[0]:</strong> {{collection[0]}}</div>
<div><strong>Collection[1]:</strong> {{collection[1]}}</div>
<div><strong>Collection[2]:</strong> {{collection[2]}}</div>
</div>
</script>
<script type="text/ng-template" id="template/popover/popover.html">
<div class="popover {{placement}}" data-ng-class="{ in: isOpen(), fade: animation() }">
<div class="arrow"></div>
<div class="popover-inner">
<h3 class="popover-title" data-ng-bind="title" data-ng-show="title"></h3>
<div class="popover-content" data-ng-bind-html="content"></div>
</div>
</div>
</script>
最佳答案
$interpolate
不处理ngRepeat
(
Difference between parse, interpolate and compile)。 $interpolate
:
要处理ngRepeat
和其他指令,您需要 $compile
。但是不幸的是,对于您的用例,$compile
将导致许多更改,因为:
$interpolate
这样的上下文。此外,还需要打开thingy
范围。这意味着我们将需要像{{thingy.blah}}这样引用您的属性,而不是模板中的{{blah}}。
因此,我们不能只在您的服务中用
$interpolate
替换$compile
。一种方法是用以下指令替换
data-ng-bind-html
,该指令的行为类似于内置ng-bind-html
的$compile
(显然,您应该仅将它与知道安全的html一起使用)。.directive('compile', function($compile) {
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
return scope.$eval(attrs.compile);
},
function(value) {
var result = element.html(value);
$compile(element.contents())(scope.$parent.$parent);
}
);
};
});
像这样使用(用
compile
代替ng-bind-html
: <div class="popover-content" compile="content"></div>
一个问题是我们需要
thingy
在范围内。有几种方法可以处理该问题,但是出于演示目的,我手动回到了弹出窗口的作用域from,这是2个作用域,即scope.$parent.$parent
。使用此编译指令,您不再需要
$interpolate
或$sanitize
,因此服务中的函数可以缩小为仅返回适当的模板:function html_for() {
var template = $templateCache.get('thingyTemplate.html');
return template;
}
demo fiddle