<input type="text" ng-model='li' fv> /* 要使用link的第四個參數有兩個必要條件 1 require存在 2 必須以屬性或類名的方式存在於一個input標籤中,而且該標籤有ng-model屬性; */ app.directive('fv', function(){ return { restrict: 'EA', require: 'ngModel', link: function(scope, ele, attr, ngmodel){ console.info('lifei',ngmodel); } } })
一下是輸出的ngModel裏面的內容
<form name='myForm'>
<input type="text" name='li1' ng-model="lifei1">
<input type="text" name="li2" pwd-match='myForm.li1' ng-model='lifei2'>
</form>ajax
//判斷兩次輸入的密碼是否相同
app.directive('myPwdMatch', [function(){ return {
//若是用link的第四個參數ctrl,必須有require:'ngModel',和類型必須是屬性 restrict: "A", require: 'ngModel', link: function(scope,element,attrs,ctrl){
//attrs.myPwdMatch的屬性值是formName.input1Name字符串,用scope.$eval()來解析字符串,獲取對應的input1Name對象 var tageCtrl = scope.$eval(attrs.myPwdMatch);
//添加自定義表單驗證的合法性 tageCtrl.$parsers.push(function(viewValue){
//設置當前input的pwdmatch的合法性,若是input1的value值 等於當前input的value值,認爲他合法 ctrl.$setValidity('pwdmatch', viewValue == ctrl.$viewValue); return viewValue; });
//當前input添加表單驗證的合法性 ctrl.$parsers.push(function(viewValue){ if(viewValue == tageCtrl.$viewValue){ ctrl.$setValidity('pwdmatch', true); return viewValue; } else{ ctrl.$setValidity('pwdmatch', false); return undefined; } }); } }; }]);
也就是說: $validators和$asyncValidators這兩個管道是$parsers管道函數數組裏面的其中兩個比較特殊的管道;json
*5. $validatorsapi
一個json對象.數組
{ validateName: function(modelValue,viewValue){ return ... } }
當$setViewValue(value)被賦值給$modelValue以前,會通過$parsers管道,通過$parsers管道時,就會通過這個$validators管道.其中validateName是驗證的名字,函數是這個驗證的方法,其中的參數modelValue和viewValue就是$modelValue和$viewValue,若是返回值是true,則經過validateNamepromise
驗證,若是返回值是false,則沒有經過validateName驗證,若是沒有經過validateName驗證,$error.validateName就會爲true.這就是angular內部驗證表單項的原理.cookie
eg: 自定義一個驗證規則,輸入內容中必須包含數字併發
<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); };
*6.$asyncValidatorsapp
一個json對象.用來處理異步驗證(好比一個http請求). 異步
{ validateName: function(modelValue,viewValue){ return promise } }
其中validateName是驗證的名字,函數是這個驗證的方法,其中的參數modelValue和viewValue就是$modelValue和$viewValue,返回值必須是一個promise對象,若是這個promise對象傳遞給它下一個.then方法失敗通知,則不經過validateName驗證,若是這個promise對象傳遞給它下一個.then方法成功通知,則表示經過validateName驗證.當異步驗證開始執行的時候,全部的異步驗證都是平行併發的.只有當全部的驗證都經過時,數據模型纔會被同步更新.只要有一個異步驗證沒有完成,這個驗證名就會被放到ngModelController的$pending屬性中.另外,全部的異步驗證都只會在全部的同步驗證經過之後纔開始.async
核心代碼:
<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() { //請求失敗 }) }; } } });
一個指令用於異步驗證是否重命名:
/*異步驗證是否重命名 * 例子: <input type="text" name="name" ng-model="form.name" create-head='{"url":"app_name/used","param":"app_name={value}"}'/> 1 自定義驗證: require,屬性 1 restrict必須是屬性,requre必須是'ngModel' 2 進行異步驗證設置 $asyncValidators = {驗證名: 驗證函數} 2 獲取請求的url,用於ajax請求 1 用先把input標籤上的createHead屬性的json字符串獲取 2 再用angular.formJson()解析成json對象 3 再用string.replace(string,value),把佔位符"{value}" 替換成input的modelValue值(scope上的值) 4 用commonService來拼接url 3 建立一個defered對象,用來返回狀態 1 用var a = $q.defer()建立 2 a.reject()表示拒絕 3 a.resolve()表示成功 4 $http請求 1 method,url,headers 2 返回的是一個promise對象 5 分狀況驗證 1 若是成功,說明找到了,命名重複,驗證不經過,返回a.reject(); 2 若是404,說明沒找到了,命名不重複,驗證經過,返回a.resolve(); 3 若是是其餘狀況,不能肯定,是否重命名,按驗證不經過算,趕回a.reject(); 6 返回一個promise對象 * */ app.directive("createHead", ["$q", "$http", "$cookies", "AppConfig", "commonService", function($q, $http, $cookies, AppConfig, commonService){ return{ restrict:"A", require:"ngModel", scope:{ version:"=" }, link:function(scope,ele,attrs,ctl){ console.info("ctrl",ctl); //格式demo: create-head='{"url":"app_name/used","param":"app_name={value}"}' ctl.$asyncValidators.checkasync = function(modelValue,viewValue){ var d = $q.defer(); //angular.formJson()方法能夠把json字符串解析成json對象; var _a = angular.fromJson(attrs.createHead); _a.url = _a.url.replace("{value}",modelValue); if(_a.param){ _a.param = _a.param.replace("{value}",modelValue); } $http({ method:"HEAD", url:commonService.getServerAuthUrl(_a.url,_a.param?_a.param:null), headers:{ "Authorization": $cookies.get("token") } }).then(function(e){ //200 已存在 d.reject(); },function(e){ if(e.status==404){ //不存在 d.resolve(); } else{ d.reject(); } }); return d.promise; }; } }; }]);