ng-repeat with ng-bind-html 作为 pre 和 post-markup
ng-repeat with ng-bind-html as pre and post-markup
我有一个包含多个对象的数组,类似于:
[
{ title: 'abc', 'pre': '<div class="class1"><div class="class2">', 'post': '</div>' },
{ title: 'def', 'pre': <div class="class3">', 'post': '</div>' },
{ title: 'ghi', 'pre': '<div class="class3">', 'post': '</div></div>' }
]
<div ng-repeat="item in myVar">
<div ng-bind-html="item.pre" />{{ item.title }}<div ng-bind-html="item.post" />
</div>
上面的方法不起作用(我必须将两个 div 合二为一,然后关闭该数组中的其他两个项目,如上图所示)。问题是 ng-bind-html 需要绑定到一个我不能使用的元素,过滤器也不起作用:
<div ng-repeat="item in myVar">
{{ item.pre | trust }}{{ item.title }}{{ item.post | trust }}
</div>
angular.module('myModule').filter('trust', ['$sce',function($sce) {
return function(value, type) { return $sce.trustAsHtml; }
}]);
有什么想法吗?
您必须执行串联预览,相信它(或打开 ngSanitize
,可能更好),然后注入它。
据我所知,无法按照您尝试的方式注入部分 HTML 元素。
在你的控制器中:
$scope.items = [...];
for (var i = 0; i < $scope.items.length; i++) {
var e = $scope.items[i];
e.concatenated = $sce.trustAsHtml(e.pre + e.title + e.post);
}
那么在你看来:
<div ng-repeat="item in items">
<div ng-bind-html="item.concatenated" />
</div>
当然,您可能希望打开 ngSanitize
,只是为了避免 e.title
出现任何问题。也就是说,如果有人输入 <script>alert('ahh!')</script>
的头衔,那将最终被信任。
由于 ngBindHtml
的写法,您的版本无法运行:
var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {
return {
restrict: 'A',
compile: function ngBindHtmlCompile(tElement, tAttrs) {
var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
return (value || '').toString();
});
$compile.$$addBindingClass(tElement);
return function ngBindHtmlLink(scope, element, attr) {
$compile.$$addBindingInfo(element, attr.ngBindHtml);
scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
// we re-evaluate the expr because we want a TrustedValueHolderType
// for $sce, not a string
element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');
});
};
}
};
}];
它使用 element.html(...)
注入,需要完整的 HTML 元素。
我有一个包含多个对象的数组,类似于:
[
{ title: 'abc', 'pre': '<div class="class1"><div class="class2">', 'post': '</div>' },
{ title: 'def', 'pre': <div class="class3">', 'post': '</div>' },
{ title: 'ghi', 'pre': '<div class="class3">', 'post': '</div></div>' }
]
<div ng-repeat="item in myVar">
<div ng-bind-html="item.pre" />{{ item.title }}<div ng-bind-html="item.post" />
</div>
上面的方法不起作用(我必须将两个 div 合二为一,然后关闭该数组中的其他两个项目,如上图所示)。问题是 ng-bind-html 需要绑定到一个我不能使用的元素,过滤器也不起作用:
<div ng-repeat="item in myVar">
{{ item.pre | trust }}{{ item.title }}{{ item.post | trust }}
</div>
angular.module('myModule').filter('trust', ['$sce',function($sce) {
return function(value, type) { return $sce.trustAsHtml; }
}]);
有什么想法吗?
您必须执行串联预览,相信它(或打开 ngSanitize
,可能更好),然后注入它。
据我所知,无法按照您尝试的方式注入部分 HTML 元素。
在你的控制器中:
$scope.items = [...];
for (var i = 0; i < $scope.items.length; i++) {
var e = $scope.items[i];
e.concatenated = $sce.trustAsHtml(e.pre + e.title + e.post);
}
那么在你看来:
<div ng-repeat="item in items">
<div ng-bind-html="item.concatenated" />
</div>
当然,您可能希望打开 ngSanitize
,只是为了避免 e.title
出现任何问题。也就是说,如果有人输入 <script>alert('ahh!')</script>
的头衔,那将最终被信任。
由于 ngBindHtml
的写法,您的版本无法运行:
var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {
return {
restrict: 'A',
compile: function ngBindHtmlCompile(tElement, tAttrs) {
var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
return (value || '').toString();
});
$compile.$$addBindingClass(tElement);
return function ngBindHtmlLink(scope, element, attr) {
$compile.$$addBindingInfo(element, attr.ngBindHtml);
scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
// we re-evaluate the expr because we want a TrustedValueHolderType
// for $sce, not a string
element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');
});
};
}
};
}];
它使用 element.html(...)
注入,需要完整的 HTML 元素。