本章主要是講指令與ngModel的交互。json
在angular有一個內置指令叫ngModel,它是angular用來處理表單的最重要的指令。在源碼中,頁面上的model值的格式化、解析、驗證都是由ngModel指令所對應的控制器ngModelController來實現的。ngModelController提供了不少方法和屬性,咱們能夠經過自定義指令的require:'ngModel'來獲取內置指令ngModel的ngModelController,進而在link函數裏對操做ngModelController的方法和屬性。api
接下來具體講一下ngModelController的方法和屬性,以及它們的具體用法。promise
1.兩個核心屬性$viewValue和$modelValue
$viewValue是指令渲染模板所用的值,而$modelValue是在控制器中流通的值。不少時候這兩個值是不同的。好比說,當頁面上展現了一個日期,顯示的多是"2018/04/23",可是這個字符串在控制器中對應的值多是一個js的Date對象的實例。app
2.三個核心管道$formatters $parses $validators 和$asyncValidators 異步
angular除了提供$viewValue和\modelValue以外,還提供了兩個用來處理它們的方法,分別是$parses和$formatters。
$parsers:由view值到model值的轉換器,用戶輸入的變化會觸發其中的管道函數,頁面上的model值由管道函數中的return值決定。
$formatters:和$parsers的做用相反,它是model值到view值的轉化器,其view值由對應的管道函數中的return值決定。
$validators: 是一個json對象async
{ validateName: function(modelValue,viewValue){ return ... } }
當$setViewValue(value)被賦值給$modelValue以前,會通過$parsers管道,通過$parsers管道時,就會通過這個$validators管道。其中,validateName是驗證器的名稱,其中的參數modelValue和viewValue就是和viewValue,若是返回值是true,則經過validateName。
自定義一個驗證器:函數
<div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.validCharacters"> <strong>Oh!</strong> 不符合自定義的驗證規則! </div>
ngModel.$validators.validCharacters = function(modelValue, viewValue) { var value = modelValue || viewValue; return /[0-9]+/.test(value); };
$asyncValidators:也是一個json對象,不過能夠用來處理異步驗證。ui
<input validate-name type="text" name="myWidget" ng-model="userContent" ng-model-options="{updateOn:'blur'}" class="form-control" required uniqueUsername> <div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.uniqueUsername"> <strong>Oh!</strong> 已經存在的用戶名! </div>
app.directive('validateName',function($http,$q){ return { restrict:'A', require:'?^ngModel', link:function(scope,iele,iattr,ctrl){ ctrl.$asyncValidators.uniqueUsername = function(modelValue, viewValue) { var value = modelValue || viewValue; // 異步驗證用戶名是否已經存在 return $http.get('/api/users/' + value). then(function resolved(res) { if(res.data){ //用戶名已經存在,驗證失敗,給下一個promise傳遞失敗通知. return $q.reject('res.data'); } else { //用戶名不存在,驗證成功. return true } }, function rejected() { //請求失敗 }) }; } } });
3.兩個核心方法$setViewValue()和$render()
$setViewValue(): 更新視圖值。緣由是每一個input的輸入事件都會調用這個方法。可是若是value是一個對象,而不是字符串或數值,那麼咱們在用該方法傳入值以前應該先拷貝一份,由於ngModel不會深刻檢測對象的變化,它只看對象的引用是否發生變化。若是隻是改變了對象的某個屬性,也不會去通過$parsers和$validators管道。執行$setViewValue()方法,不會觸發$digest。
$render():在視圖須要被更新的時候調用。因爲ngModel的對比機制,$render()只在$modelValue和$viewValue都發生了實際的改變, 纔會會被調用。也就是說,$render函數負責將模型值同步到視圖上。spa
來看一下指令和控制器及其內部運做如圖:
rest
還有一些經常使用屬性
屬性 | 說明 |
---|---|
$error | json對象。就是全部驗證失敗的驗證名和失敗信息組成的json對象。 |
$pending | json對象。正在進行中的異步驗證會被放在這個對象裏。 |
$untouched | 布爾值。若是元素尚未失去過焦點,那這個值就是true。 |
$touched | 布爾值。若是元素已經失去過焦點,那這個值就是false。 |
$pristine | 布爾值。若是元素尚未和用戶發生過交互,那這個值就是true。 |
$dirty | 布爾值。若是元素已經和用戶發生過交互,那這個值就是true。 |
$valid | 布爾值。這個也很經常使用,就是當全部驗證(異步同步),都經過的時候,它就是true。 |
$invalid | 布爾值。這個也很經常使用,就是當全部驗證(異步同步),其中有一個或一個以上驗證失敗,它就是true。 |
$name | 字符串。很簡單,就是獲取元素的name屬性。 |
$isEmpty | 當咱們須要判斷input的value值是否爲空的時候,可使用這個方法。 |