为什么ng-bind-html和$ sanitize会产生不同的结果? [英] Why do ng-bind-html and $sanitize produce different results?
问题描述
我正在尝试清理某些文本区域的内容,我不能使用ng-bind-html
,因为它破坏了两种方式的绑定(ng-model
不能同时工作)
I'm trying to sanitize the content of some text areas, I cannot use ng-bind-html
because it breaks two way binding (ng-model
does not work at the same time)
奇怪的是,当我将ng-bind-html
应用于模型时,它会产生与在指令内部使用$sanitize
或$sce
时不同的结果.
Strangely when I apply ng-bind-html
to a model it produces a different result to when I use $sanitize
or $sce
inside of a directive.
这是我制作的一个样本
http://plnkr.co/edit/iRvK4med8T9Xqs22BkOe?p=preview
第一个文本区域使用ng-bind-html
,第二个文本区域使用$sanitize
,第三个区域应该是ng-bind-html指令的代码,因为我是从AngularJS源代码中剥离出来的.
First text area uses ng-bind-html
, the second uses $sanitize
and the third should be the code for the ng-bind-html directive as I ripped out of the AngularJS source code.
"
仅在使用ng-bind-html时更正为更改为"
,在其他两个示例中,其更改为"
"
is only corrected changed to "
when using ng-bind-html, in the other two examples it changes to "
如何在指令中复制ng-bind-html
的结果-同时保持双向绑定?
How can I replicate the results of ng-bind-html
in my directive - while keeping the two way binding?
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>
推荐答案
事实证明,卫生服务正在返回相同的结果.在 ngBindHtmlDirective ,我们可以介入并查看正在发生的情况.我们深入研究
It turns out like we would expect, the sanitation service is returning the same result. Placing a breakpoint inside the ngBindHtmlDirective, We can step in and see what is happening. We dive in and examine the values inside the $SanitizeProvider. The value of buf
that will be returned back to the ngBindHtmlDirective is:
在"引用"测试
This in "quotes" for testing
与调用$ sanitize所获得的完全一样,那么真正的区别是什么?真正的区别在于文本框的innerHTML和值之间.查看此示例监听器.您可以看到调用两种不同的方法以及用不同的转义双引号的方法之间的区别.我没有深入研究w3规范或浏览器代码,但我假设innerHTML分配在创建documentFragment,抓取它的textContent,然后将其分配给文本框的值的功能下进行了其他工作.显然,值只是获取字符串并按原样插入.
The exact same as we get for calling $sanitize, so what's the real difference? The real difference is between a textbox's innerHTML and value. View this example plunker. You can see the difference between calling the two different methods, with the different ways of escaping a double quote. I didn't go digging though the w3 spec or the browser code, but I assume the innerHTML assignment is doing additional work under the hood of creating a documentFragment, grabbing it's textContent, then assigning that to the textbox's value. Obviously value is just grabbing the string and inserting it as is.
那么您的指令有什么问题?我看到element.html(processed)
在注释中,但取消注释不会产生任何影响.好吧,事实是它确实可以瞬间工作!尽管逐步使用调试器,但仍正确设置了文本框的值,但随后会触发$ digest循环并立即对其进行更改!事实是ngModelDirective遇到了麻烦,特别是
So what's the problem with your directives? I see that element.html(processed)
is in a comment, but uncommenting it doesn't have an affect. Well the truth is that it does work for a split second! Stepping though with the debugger, the value of the textbox is correctly set, but then a $digest cycle gets fired and immediate changes it! The truth is the ngModelDirective is getting in the way, specifically it's the $render function of the baseInputType. We can see in the code it is using the element.val
method.
如何在指令中解决此问题?要求ngModelController并覆盖其$ render函数以改用element.html
方法(示例监听器 ).
How can we fix this in the directives? Require the ngModelController and override its $render function to use element.html
method instead (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);
};
这篇关于为什么ng-bind-html和$ sanitize会产生不同的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!