AngularJS表單驗證及狀態
在處理表單尤其驗證各種狀態的表單和輸入時,AngularJS怎樣還能讓我們受益:
<html ng-app="notesApp"><head><title>Notes App</title></head><body ng-controller="MainCtrl as ctrl"> <form ng-submit="ctrl.submit()" name="myForm"> <input type="text" ng-model="ctrl.user.username" required ng-minlength="4"> <input type="password" ng-model="ctrl.user.password" required> <input type="submit" value="Submit" ng-disabled="myForm.$invalid"> </form><script src="http://riafan.com/libs/angular.js"></script><script type="text/javascript"> angular.module('notesApp', []) .controller('MainCtrl', [function() { var self = this; self.submit = function() { console.log('User clicked submit with ', self.user); }; }]);</script></body></html>
在下面這個例子中,我們修改前面樣本添加一些驗證。特別是如果使用者沒有填寫所有必要欄位,我們要禁用提交按鈕。我們如何做到這一點呢?
我們給表單取名字myForm,供以後參考。
我們使用HTML5驗證標籤為每個輸入欄位添加required屬性。
我們添加ng-minlength驗證器,強制username輸入文本的最小長度值為4個字元。
我們點擊Submit按鈕,添加一個ng-disabled指令。如果條件成立會禁用元素。
我們使用表單暴露具有目前狀態的表單控制器。在這種情況下,如果名為myForm的表單的$invalid為true則禁用按鈕。
當您使用表單(給他們命名),AngularJS建立FormController儲存表單的目前狀態及一些輔助方法。正如我們在前面的例子使用myForm,您可以通過表單名訪問FormController表單。作為狀態公開並和資料繫結保持最新同步的屬性如下表所示。
表4-1. AngularJS中的表單狀態
表單狀態 |
描述 |
$invalid |
當任一驗證(required、ng-minlength等)標識表單的任一欄位為無效時AngularJS設定這種狀態 |
$valid |
與$invalid相反,設定所有表單驗證目前評估為正確狀態 |
$pristine |
AngularJS中所有表單從該狀態開始。這允許你找出使用者是否開始輸入並修改任何錶單元素。可能的用法:表單原始狀態下禁用reset按鈕。 |
$dirty |
與$pristine相反。即使用者做了一些更改(他可以恢複,但$dirty標識已經設定)。 |
$error |
包含控制項或表單驗證失敗的引用。在接下來的章節我們將進一步討論這部分。 |
表中提到的每個狀態都是布爾值,可以用來有條件地隱藏、顯示、禁用或啟用HTML使用者介面元素。當使用者輸入或修改表單時,只要使用ng-model和表單名,狀態值就會同步更新。
AngularJS表單的錯誤處理
我們已經講解能在在表單層面檢驗的多種類型驗證,但個別欄位呢?在前面的樣本中,我們確保輸入欄位都是必要欄位,username的最小長度是4個。我們還能做什嗎?表4-2包含了AngularJS的一些內建驗證。
表4-2. AngularJS內建的驗證器
驗證器 |
描述 |
required |
正如前面所討論的那樣,這確保欄位是必需的,欄位標記為無效,直到填寫。 |
ng-required |
與required不同,這標誌著欄位也是必需的,ng-required指令允許我們基於控制器布爾條件標記輸入欄位為必需。 |
ng-minlength |
該指令可以設定輸入文本值的最小長度 |
ng-maxlength |
該指令可以設定文本輸入值的最小長度 |
ng-pattern |
作為這個指令的一部分,文本輸入的有效性可以針對指定的Regex模式進行檢查。 |
type=”email” |
文本輸入內建電子郵件驗證。 |
type=”number” |
帶有數量驗證的文本輸入。也可以有最小和最大值的附加屬性。 |
type=”date” |
如果瀏覽器支援,顯示一個HTML日期選取器。否則,預設為一個文本輸入。ng-model 綁定到日期對象。預計日期格式為yyyy-mm-dd(例如2009-10-24)。 |
type=”url” |
帶有輸入驗證的URL文本輸入。 |
此外,我們可以編寫自己的驗證器,我們將在後面章節這個問題。
顯示錯誤訊息
我們能用這些驗證器做些什麼呢?當然可用來檢查表單的有效性,並相應地禁用儲存或更新按鈕。但是我們也要告訴使用者錯在哪裡、如何修正。AngularJS提供兩種方案來解決這個問題:
模型準確反映表單錯誤是什麼,我們可以使用它來顯示更友好的錯誤訊息。
自動從每個欄位添加和刪除的CSS類允許我們的突出表單錯誤。
首先讓我們看一看如何根據錯誤對象顯示特定的錯誤訊息,看下面的例子:
<html ng-app="notesApp"><head><title>Notes App</title></head><body ng-controller="MainCtrl as ctrl"> <form ng-submit="ctrl.submit()" name="myForm"> <input type="text" name="uname" ng-model="ctrl.user.username" required ng-minlength="4"> <span ng-show="myForm.uname.$error.required"> This is a required field </span> <span ng-show="myForm.uname.$error.minlength"> Minimum length required is 4 </span> <span ng-show="myForm.uname.$invalid"> This field is invalid </span> <input type="password" name="pwd" ng-model="ctrl.user.password" required> <span ng-show="myForm.pwd.$error.required"> This is a required field </span> <input type="submit" value="Submit" ng-disabled="myForm.$invalid"> </form><script src="http://riafan.com/libs/angular.js"></script><script type="text/javascript"> angular.module('notesApp', []) .controller('MainCtrl', [function() { var self = this; self.submit = function() { console.log('User clicked submit with ', self.user); }; }]);</script></body></html>
在本例中控制器中沒有做任何改變。相反,我們可以只需要關注表單的HTML。讓我們看看錶單改變子什麼:
首先,我們為需要驗證的兩個輸入欄位添加了name屬性,使用者名稱文本命名為uname,pwd密碼文本命名為pwd。
然後使用AngularJS的表單綁定能夠為每個表單欄位找出錯誤。當我們為任何輸入表單添加name屬性時,實際上專門為它建立了帶有錯誤狀態的模型。
所以對於使用者名稱欄位,我們可以通過訪問myForm.uname$error.required來檢驗它有沒有填寫。同樣對於ng-minlength,欄位應該是myForm.uname.$error.minlength。對於密碼,我們通過myForm.pwd.$error.required來檢驗該欄位是否填寫。
類似於表單,我們也通過myForm.uname.$invalid訪問輸入狀態。我們早些時候講述的其他所有表單狀態($valid、 $pristine和$dirty)也同樣適用於myForm.uname對象。
通過模型,現在只有當某種類型的錯誤觸發時才顯示一個錯誤訊息。上表中的每一個驗證器公開了錯誤對象的相應鍵。因此,我們可以把它找到並將特定的錯誤訊息顯示給使用者。需要顯示給使用者名稱那個欄位是必需的嗎?然後當使用者開始打字時,顯示了輸入的最小長度,最後當輸入超過最大長度時顯示一條訊息。所有這些類型的條件資訊都可以使用AngularJS驗證器來顯示。
為表單和狀態設定樣式
我們看到了各種狀態的形式(輸入):$dirty、$valid等。我們看到如何根據這些條件顯示特定的錯誤訊息和禁用按鈕,但是如果我們想使用使用者介面和CSS強調某些輸入欄位或表單狀態呢?一種選擇是與ng-class指令一起使用表單和輸入狀態,比如myForm.$dirty為真時添加dirty類。但AngularJS提供了一個更容易的選擇。
對於每個我們上文描述狀態,AngularJS為表單和輸入元素來回添加和刪除CSS類,如表4-3所示。
表4-3. 表單狀態CSS類
表單狀態 |
應用的CSS類 |
$invalid |
ng-invalid |
$valid |
ng-valid |
$pristine |
ng-pristine |
$dirty |
ng-dirty |
同樣,對於每個添加到輸入欄位的驗證器,我們也可以用類似的命名方式的CSS類,如下表4-4所示。
表4-4. 輸入狀態CSS類
輸入狀態 |
應用的CSS類 |
$invalid |
ng-invalid |
$valid |
ng-valid |
$pristine |
ng-pristine |
$dirty |
ng-dirty |
required |
ng-valid-required或ng-invalid-required |
min |
ng-valid-min或ng-invalid-min |
max |
ng-valid-max或ng-invalid-max |
pattern |
ng-valid-pattern或ng-invalid-pattern |
url |
ng-valid-url或ng-invalid-url |
email |
ng-valid-email或ng-invalid-email |
date |
ng-valid-date或ng-invalid-date |
number |
ng-valid-number or ng-invalid-number |
除了基本的輸入狀態,AngularJS還需要驗證器的名稱(數量,最大長度、模式等),根據特定的驗證器是否滿足需求,相應添加ng-valid-validator_name或ng-invalid-validator_name類。
讓我們看一個可以以不同的方式來強調輸入的樣本:
在這個例子中,我們保留子現有的驗證器功能,雖然我們移除特定的錯誤訊息。相反,我們試圖做的是使用CSS的類標出所需欄位。這是完成的樣本:
正確填寫欄位時,輸入框變綠色。這是當CSS類ng-valid應用於我們的輸入欄位時通過設定背景顏色來完成的。
如果使用者開始輸入時我們要顯示深紅色背景,然後撤銷它。也就是說,我們要將背景設定為紅色,標記為必需的欄位,但只有在使用者修改欄位後。所以我們設定背景顏色是紅色的,如果應用
CSS類ng-dirty(標識使用者已修改)ng-invalid-minlength(標識使用者沒有輸入足夠數量的字元)。
類似地,如果欄位是必需的但不是髒的,您可以添加一個CSS類用紅色*來顯示。從頭開始使用這些CSS類的組合(表單和輸入狀態),您可以便於使用樣式,將所有相關的、可操作的使用者介面呈現給使用者。