$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>