Dav*_*ers 22 angularjs angularjs-directive
我制作了一个指令,旨在使用ngModel指令附加到元素.如果模型的值匹配,则应将值设置为先前的值.在我的例子中,我正在寻找"foo",并将其设置回前一个,如果这是输入的内容.
我的单元测试在这方面很好,因为他们只关注模型值.但是在实践中,当"回放"触发时,DOM不会更新.我们在这里最好的猜测是设置old == new可以防止脏检查发生.我逐步完成了$ setViewValue方法,它看起来正在做它应该做的事情.但是,在我设置新值之后显式调用ngModel.$ render()之前,它不会更新DOM(以及您在浏览器中看到的内容).它工作正常,但我只想看看是否有更合适的方法.
angular.module('myDirective', [])
.directive('myDirective', function () {
return {
restrict: 'A',
terminal: true,
require: "?ngModel",
link: function (scope, element, attrs, ngModel) {
scope.$watch(attrs.ngModel, function (newValue, oldValue) {
//ngModel.$setViewValue(newValue + "!");
if (newValue == "foo")
{
ngModel.$setViewValue(oldValue);
/*
I Need this render call in order to update the input box; is that OK?
My best guess is that setting new = old prevents a dirty check which would trigger $render()
*/
ngModel.$render();
}
});
}
};
});
function x($scope) {
$scope.test = 'value here';
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*ord 33
我们在这里最好的猜测是设置old == new可以防止脏检查发生
仅当其正在侦听的表达式的值发生更改时,才会调用观察者侦听器.但是,由于您将模型更改回其先前的值,因此不会再次调用它,因为它的值根本没有变化.但是,要小心:在观察者内部更改属性的值,监视同一属性可能导致无限循环.
但是,在我设置新值之后显式调用ngModel.$ render()之前,它不会更新DOM(以及您在浏览器中看到的内容).
那是对的.$setViewValue将模型值设置为视图更新,但您需要调用$render以基于(新)模型值有效地呈现视图.有关更多信息,请查看此讨论.
最后,我认为你应该以不同的方式处理你的问题.您可以使用$parsers属性NgModelController来验证用户输入,而不是使用观察者:
link: function (scope, element, attrs, ngModel) {
if (!ngModel) return;
ngModel.$parsers.unshift(function(viewValue) {
if(viewValue === 'foo') {
var currentValue = ngModel.$modelValue;
ngModel.$setViewValue(currentValue);
ngModel.$render();
return currentValue;
}
else
return viewValue;
});
}
Run Code Online (Sandbox Code Playgroud)
我更改了你的jsFiddle脚本以使用上面的代码.
angular.module('myDirective', [])
.directive('myDirective', function () {
return {
restrict: 'A',
terminal: true,
require: "?ngModel",
link: function (scope, element, attrs, ngModel) {
if (!ngModel) return;
ngModel.$parsers.unshift(function(viewValue) {
if(viewValue === 'foo') {
var currentValue = ngModel.$modelValue;
ngModel.$setViewValue(currentValue);
ngModel.$render();
return currentValue;
}
else
return viewValue;
});
}
};
});
function x($scope) {
$scope.test = 'value here';
}Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<h1>Foo Fighter</h1>
I hate "foo", just try and type it in the box.
<div ng-app="myDirective" ng-controller="x">
<input type="text" ng-model="test" my-directive>
<br />
model: {{test}}
</div>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
27436 次 |
| 最近记录: |