與KO相比,NG的內建資料驗證功能強大許多。先看示範:
載入網頁時欄位均為白底,輸入資料後會觸發檢核,輸入值有效呈現綠底,不合要求則為紅底。變色關鍵來自以下CSS設定,NG會在使用者輸入資料後新增ng-dirty class,依檢核成功或失敗加上ng-valid或ng-invalid:
form .ng-invalid.ng-dirty { background-color: pink; }
form .ng-valid.ng-dirty { background-color: lightgreen; }
第一欄文字屬必填,加上required Directive即可,寫成<input name="text" ng-model="model.text" required />。
電子郵件欄位限定需為有效電子郵件地址,格式不符時後方會顯示錯誤提示,做法如下:
<inputtype="email"name="emailAddr"ng-model="model.emailAddr"required/>
<spanclass="invld-hint"
ng-show="myForm.emailAddr.$invalid && myForm.emailAddr.$dirty">
<spanng-show="myForm.emailAddr.$error.email">Email格式不正確</span>
<spanng-show="myForm.emailAddr.$error.required">必填欄位</span>
</span>
model為ViewModel物件,model.emailAdddr為普通的JavaScript屬性,NG提供.$error.emai檢測其值是否為有效Email地址格式(符合格式時傳回false),透過ng-show="myForm.emailAddr.$error.email"可決定後方錯誤提示顯示或隱藏。NG內建required, pattern, minlength, maxlength, min, max六種檢核Drective。[參考]
第三欄使用ng-minlength、ng-maxlength限制長度需為4-6個字元,ng-pattern指向Regular Expression限定[0-9A-Za-z],範例中ng-pattern繫結到ViewModel屬性,必要時可動態指定。
<inputtype="text"name="code"ng-model="model.code"ng-minlength="4"ng-maxlength="6"
ng-pattern="model.codePattern"/>
<spanclass="invld-hint"ng-show="myForm.code.$error.pattern">需為0-9, A-Z, a-z</span>
輸入內容繫結到{{model | json}},相當於整個ViewModel JSON序列化的結果,實測可發現,NG會自動排除檢核失敗欄位。
由上述觀察足以證明NG的ViewModel具備資料狀態概念,能掌握欄位是否被修改過(一開始白底,輸入後呈現綠底或紅底)以及欄位是否符合檢核要求,故在網頁下方加上表單狀態旗標顯示加以佐證。本範例表單命名為myForm(<form name="myForm">),由$scope.myForm.$pristine等參數可取得表單狀態,包含:[參考]
- $pristine: 是否為原始狀態,使用者尚未更動?
- $dirty: 使用者是否有更動任何內容?
- $valid: 是否所有欄位都通過檢核?
- $error: 表單各欄位的檢核結果,範例使用$error | json已濾掉$開頭的Angular專用參數,實際上我們可由$error取得欄位名稱等細節。
另外,利用<input type="submit" value="送出" ng-disabled="myForm.$invalid" />限定通過檢核才允許送出表單,也是常見的規格需求。
以下為完整範例:Live Demo
<!DOCTYPEhtml>
<htmlng-app="sampleApp">
<head>
<metacharset="utf-8">
<title>Lab 17 - 資料檢核</title>
<style>
body, input
{
font-size: 9pt;
}
form .ng-invalid.ng-dirty { background-color: pink; }
form .ng-valid.ng-dirty { background-color: lightgreen; }
.invld-hint { color: red; }
.invld-hint span { margin-right: 6px; }
</style>
</head>
<bodyng-controller="defaultCtrl">
<formname="myForm">
<p>
請輸入文字:
<inputname="text"ng-model="model.text"required/>
</p>
<p>
請輸入電子郵件:
<inputtype="email"name="emailAddr"ng-model="model.emailAddr"required/>
<spanclass="invld-hint"
ng-show="myForm.emailAddr.$invalid && myForm.emailAddr.$dirty">
<spanng-show="myForm.emailAddr.$error.email">Email格式不正確</span>
<spanng-show="myForm.emailAddr.$error.required">必填欄位</span>
</span>
</p>
<p>
請輸入4-6位英數字
<inputtype="text"name="code"ng-model="model.code"ng-minlength="4"ng-maxlength="6"
ng-pattern="model.codePattern"/>
<spanclass="invld-hint"ng-show="myForm.code.$error.pattern">需為0-9, A-Z, a-z</span>
</p>
<p>
輸入內容={{model | json}}
</p>
<div>
表單狀態:
$pristine={{myForm.$pristine}},
$dirty={{myForm.$dirty}},
$valid={{myForm.$valid}}, <br/>
$error={{myForm.$error | json}}
</div>
<hr/>
<inputtype="submit"value="送出"ng-disabled="myForm.$invalid"/>
<inputtype="button"value="Debug"ng-click="model.debug()"/>
</form>
<scriptsrc="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script>
angular.module("sampleApp", [])
.controller("defaultCtrl", function($scope) {
function myViewModel() {
var self = this;
self.text = "";
self.emailAddr = "";
self.code = "";
self.codePattern = new RegExp("^[0-9a-zA-Z]*$");
}
$scope.model = new myViewModel();
});
</script>
</body>
</html>
[NG系列]