標籤:
雖然我不是前端程式員,但明白前端做好驗證是多麼重要。
因為這樣後端就可以多喘口氣了,而且相比後端什麼的果然還是前端可以提高使用者的幸福感。
AngularJS提供了很方便的表單驗證功能,在此記錄一番。
首先從下面這段代碼開始
<form ng-app="myApp" ng-controller="validationController" name="mainForm" novalidate> <p>Email: <input type="email" name="email" ng-model="email" required> <span style="color:red" ng-show="mainForm.email.$dirty && mainForm.email.$invalid"> <span ng-show="mainForm.email.$error.required">Email is required.</span> <span ng-show="mainForm.email.$error.email">Invalid email address.</span> </span> </p> <p> <input type="submit" ng-disabled="mainForm.$invalid"> </p></form><script>angular.module(‘myApp‘,[]).controller(‘validationController‘, [‘$scope‘,function($scope) { $scope.user = ‘Kavlez‘; $scope.email = ‘[email protected]‘;}]);</script>
input標籤的一些驗證選項,通常和HTML5標記搭配使用。
必填
<input type="text" required />
長度
使用指令ng-minlength/ng-maxlength
<input type="text" ng-minlength="5" />
特定格式
例如電子郵件、URL、數字,將type設定為相應類型即可,例如:
<input type="email" name="email" ng-model="user.email" /><input type="number" name="age" ng-model="user.age" /><input type="url" name="homepage" ng-model="user.facebook_url" />
模式比對
使用指令ng-pattern,例如:
<input type="text" ng-pattern="[a-z]" />
表單屬性,通過這些屬性可以更容易地對錶單進行操作
$pristine / $dirty
表示是否已修改,例如
<form name="mainForm" ng-controller="orderController"><input type="email" name="userEmail" ng-model="myEmail" /> {{mainForm.userEmail.$pristine}} {{mainForm.userEmail.$dirty}}</form>
以formName.fieldName.$pristine方式訪問,input必須有ng-model聲明。
AngularJS為表單狀態提供了相應地css class
- .ng-pristine
- .ng-dirty
- .ng-valid
- .ng-invalid
例如,讓驗證通過為綠色,失敗為紅色:
input.ng-valid { color: green;}input.ng-invalid { color: green;}
給出的例子中僅僅是一個email的驗證就寫了這麼多,如果再加幾個field,再加幾種不同的提示,再加上幾個事件,代碼會變得雜亂不堪。
事實上並不推薦這樣做,我們有更好的方法。
就是使用angular-messages.js
首先,不要忘了這兩步
好,先用ng-messages和ng-message替換掉那些重複的東西,上面的例子變成:
<form ng-controller="validationController" name="mainForm" > <p>Email: <input type="email" name="email" ng-model="myEmail" ng-minlength="3" ng-maxlength="50" required /> <div style="color:red" ng-messages="mainForm.email.$error" ng-messages-multiple> <p class="error" ng-message="required">Email is required.</p> <p class="error" ng-message="email">Invalid email address.</p> <p class="error" ng-message="minlength">min length 10</p> <p class="error" ng-message="maxlength">max length 50</p> </div> </p> <p> <input type="submit" ng-disabled="mainForm.$invalid" /> </p></form>
功能上沒有任何變化,只是把重複的代碼全部去掉了。
注意區分ng-messasges和ng-message,有沒有感覺有點像with()?後面的ng-messages-multiple,這裡用作同時讓多個提示出現。
但這樣仍然不夠好,就算省去了ng-message中的內容,但是多個field中都存在required驗證時仍然會有重複。
而且,如果不同頁面中的表單都涉及到相同的內容時重複的驗證提示會越來越多。
為瞭解決這個問題,我們可以使用ng-messages-include指令。
該指令用來引用模板,比如上面的例子變為:
<form ng-controller="validationController" name="mainForm" > <p>Email: <input type="email" name="email" ng-model="myEmail" ng-minlength="3" ng-maxlength="50" required /> <div style="color:red" ng-messages="mainForm.email.$error" ng-messages-multiple ng-messages-include="validateTemplate/email.html"> </div> </p> <p> <input type="submit" ng-disabled="mainForm.$invalid" /> </p></form>
並不複雜,我們再加點東西。
為了讓提示更友好(?)一些,我們試試實現游標離開後出現提示的效果。
這時候用指令(directive)會方便很多,在這裡先涉及一點和指令相關的內容。
先運行起來再說:
var myApp = angular.module(‘myApp‘,[]) .controller(‘validationController‘, [‘$scope‘,function($scope) { $scope.user = ‘Kavlez‘; $scope.email = ‘[email protected]‘; }]) .directive(‘hintOnBlur‘, [function() { return { require: ‘ngModel‘, link: function(scope, element, attrs, ctrl) { ctrl.focused = false; element.bind(‘focus‘, function(evt) { scope.$apply(function() {ctrl.focused = true;}); }).bind(‘blur‘, function(evt) { scope.$apply(function() {ctrl.focused = false;}); }); } } }]);
此處我們用focused來判斷游標是否在某個屬性上,當使用了hintOnBlur指令的對象上發生focus或blur事件時focused的狀態發生變化。
表單也跟著改變一下,使用方法如下:
<form ng-controller="validationController" name="mainForm" > <p>Email: <input type="email" name="email" ng-model="myEmail" ng-minlength="3" ng-maxlength="50" required hint-on-blur /> <div style="color:red" ng-messages="mainForm.email.$error" ng-show="!mainForm.email.focused" ng-messages-multiple ng-messages-include="validateTemplate/email.html"> </div> </p> <p> <input type="submit" ng-disabled="mainForm.$invalid" /> </p></form>
在ng-show中再加入對focused的判斷,false時出現提示。
現在看起來像那麼回事了。
自訂驗證方式與有效性(validity),這個也用到指令(directive)。
驗證填寫的email是否已佔用,這裡簡單類比一下:
.directive(‘isAlreadyTaken‘, function() { return { require: ‘ngModel‘, link: function(scope, ele, attrs, ctrl) { ctrl.$parsers.push(function(val) { ctrl.$setValidity(‘emailAvailable‘, false); var emailTable = [ ‘[email protected]‘, ‘[email protected]‘, ‘[email protected]‘, ‘[email protected]‘, ‘[email protected]‘, ‘[email protected]‘]; for (var i=0;i<emailTable.length;i+=1) if(val==emailTable[i]) return; ctrl.$setValidity(‘emailAvailable‘, true); return val; }) } }})
Input元素中加上is-already-taken屬性,並且再加一個ng-message:
<p class="error" ng-message="emailAvailable">Already taken! try other email addresses!</p>
AngularJS - 表單驗證