我试图清理某些文本区域的内容,但我无法使用ng-bind-html
因为它违反了双向绑定(ng-model
无法同时工作)
奇怪的是,当我将ng-bind-html
应用于模型时,它会在指令中使用$sanitize
或$sce
时产生不同的结果。
这是我编写的一个样本
http://plnkr.co/edit/iRvK4med8T9Xqs22BkOe?p=preview
第一个文本区域使用ng-bind-html
,第二个文本区域使用$sanitize
,第三个文本区域应该是我从AngularJS源代码中删除的ng-bind-html指令的代码。
"
仅在使用ng-bind-html时更正为"
,在其他两个示例中更改为"
如何在我的指令中复制ng-bind-html
的结果 - 同时保持双向绑定?
angular.module('sanitizeExample', ['ngSanitize'])
.controller('ExampleController', ['$scope', '$sce',
function($scope, $sce) {
$scope.value = 'This in "quotes" for testing';
$scope.model = 'This in "quotes" for testing';
}
]).directive('sanitize', ['$sanitize', '$parse', '$sce',
function($sanitize, $parse, $sce) {
return {
restrict: 'A',
replace: true,
scope: true,
link: function(scope, element, attrs) {
var process = function(input) {
return $sanitize(input);
//return $sce.getTrustedHtml(input);
};
var processed = process(scope.model);
console.log(processed); // Output here = This in "quotes" for testing
$parse(attrs.ngModel).assign(scope, processed);
//element.html(processed);
}
};
}
])
.directive('sanitizeBindHtml', ['$parse', '$sce',
function($parse, $sce) {
return {
restrict: 'A',
replace: true,
scope: true,
link: function(scope, element, attrs) {
var parsed = $parse(attrs.ngModel);
function getStringValue() {
var value = parsed(scope);
getStringValue.$$unwatch = parsed.$$unwatch;
return (value || '').toString();
}
scope.$watch(getStringValue, function ngBindHtmlWatchAction(value) {
var processed = $sce.getTrustedHtml(parsed(scope)) || '';
$parse(attrs.ngModel).assign(scope, processed)
});
}
};
}
]);

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-sanitize.js"></script>
<!doctype html>
<html lang="en">
<body ng-app="sanitizeExample">
<div ng-controller="ExampleController">
<textarea ng-bind-html="value"></textarea>
<br/>{{value}}
<br/>
<br/>
<textarea sanitize ng-model="model"></textarea>
<br/>
<br/>
<textarea sanitize-bind-html ng-model="model"></textarea>
</div>
</body>
&#13;
答案 0 :(得分:2)
事实证明,卫生服务正在回归相同的结果。在ngBindHtmlDirective内放置一个断点,我们可以介入,看看发生了什么。我们深入研究$SanitizeProvider内的值。将返回ngBindHtmlDirective的buf
值为:
这个&##;引用&amp;#34;用于测试
与我们调用$ sanitize完全相同,那么真正的区别是什么?真正的区别在于文本框的innerHTML和值之间。查看此example plunker。您可以看到调用两种不同方法之间的区别,使用不同的方法来转义双引号。我没有去挖掘w3规范或浏览器代码,但我认为innerHTML赋值是在创建documentFragment,抓取它的textContent,然后将其分配给文本框的值的引擎下做额外的工作。显然,值只是抓住字符串并按原样插入。
那么你的指令有什么问题?我看到element.html(processed)
在评论中,但取消注释它没有影响。嗯,事实是它确实工作了一瞬间!使用调试器逐步调试,文本框的值被正确设置,然后$ digest循环被触发并立即更改它!事实是ngModelDirective正在阻碍,特别是它是$render function of the baseInputType。我们可以在代码中看到它使用的是element.val
方法。
我们如何在指令中解决这个问题?需要ngModelController并覆盖其$ render函数以改为使用element.html
方法(example plunker)。
// Add require to get the controller
require: 'ngModel',
// Controller is passed in as the 4th argument
link: function(scope, element, attrs, ngModelCtrl) {
// modify the $render function to process it as HTML
ngModelCtrl.$render = function() {
element.html(ngModelCtrl.$isEmpty(ngModelCtrl.$viewValue) ? '' : ngModelCtrl.$viewValue);
};