$parsers 首先先了解下它具体的作用,当用户与控制器进行交互的时候。ngModelController中的$setViewValue()方法就会被调用,$parsers的数组中函数就会以流水线的形式被一一调用。第一个$parse被调用后在进行第二个$parse调用
这些函数可以对输入值进行转换,后者通过$setValidity()函数设置表达的合法性:
这个方法可以人为的设置一个表单控件的$valid 以及$ invalid, 也就是说改变表单控件是否通过校验的状态.类似的还有$setDirty()和$setPristine().
那么具体是实现,用了一些时间做了一个突击测试,也没有花什么时间研究,有不妥也正常,但应该也差不多了
首先$parsers是view 到 model的一个过度,因此当Model不希望有所更新的时候就返回一个undefined。
其实初步看它是改变了ngModel的值,但测试会发现你在输入Input里面并没有为空,还是你输入的数,但你会发现如果它被触发了,Model里面的属性就不会更新了,所以因此当Model不希望有所更新的时候就返回一个undefined。这句话是没有问题的。它只是Model不去更新了,但你的view还是会更新的,因为我们输入的内容不还是在ng-model内么,只是他不和Model相连接了,嗯我的理解就是失去了双向绑定的特性,封闭“作用域”。
这个服务多用在指令上,那么经过测试发现只要你要用到指令了就必须加上他,即使你感觉根本没有地方调用它,但是它确实是存在那的。
如你把下面的例子ng-test 去点看看 然后加上属性不调用在看看,以及就像我就写个ng-test 看看。
那么具体什么时候是model转向view就是另一个内置服务了$formatters,那么这个其实也是$parsers执行后立即调用的服务。这就不多说了。
//HTML
<div ng-controller="TestController">
<form name="testForm">
<input type="text" name="inputs" ng-test ng-model="obj.number">
<span ng-show="testForm.inputs.$error.test">good</span>
<span ng-hide="testForm.inputs.$error.test">bad</span>
<div>{{ testForm.inputs.$valid }}</div>
<div>{{ testForm.inputs.$invalid }}</div>
<div>{{ obj.number }}</div>
</form>
</div>
//Script
<script type="text/javascript">
angular.module('myApp', [])
.controller('TestController', function($scope) {
$scope.obj = {
number: 34
};
})
.directive('ngTest', function(){
return {
require: '?ngModel',
restrict: 'AE',
link: function($scope, iElm, iAttrs, ngModel) {
if(!ngModel) return;
ngModel.$parsers.push(function(viewValue){
var num = parseInt(viewValue);
if(num>=0 && num<99){
ngModel.$setValidity('test',true);
return viewValue;
}else{
ngModel.$setValidity('test',false);
return undefined;
}
});
}
};
});
</script>