與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 />。

電子郵件欄位限定需為有效電子郵件地址,格式不符時後方會顯示錯誤提示,做法如下:

    <input type="email" name="emailAddr" ng-model="model.emailAddr" required />
    <span class="invld-hint" 
     ng-show="myForm.emailAddr.$invalid && myForm.emailAddr.$dirty">
      <span ng-show="myForm.emailAddr.$error.email">Email格式不正確</span>
      <span ng-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屬性,必要時可動態指定。

<input type="text" name="code" ng-model="model.code" ng-minlength="4" ng-maxlength="6" 
ng-pattern="model.codePattern" />
<span class="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

<!DOCTYPE html>
<html ng-app="sampleApp">
<head>
  <meta charset="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>
<body ng-controller="defaultCtrl">
  <form name="myForm">
  <p>
  請輸入文字:
  <input name="text" ng-model="model.text" required />
  </p>
  <p>
    請輸入電子郵件:
    <input type="email" name="emailAddr" ng-model="model.emailAddr" required />
    <span class="invld-hint" 
     ng-show="myForm.emailAddr.$invalid && myForm.emailAddr.$dirty">
      <span ng-show="myForm.emailAddr.$error.email">Email格式不正確</span>
      <span ng-show="myForm.emailAddr.$error.required">必填欄位</span>
    </span>
  </p>
  <p>
    請輸入4-6位英數字
    <input type="text" name="code" ng-model="model.code" ng-minlength="4" ng-maxlength="6" 
     ng-pattern="model.codePattern" />
    <span class="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 />
  <input type="submit" value="送出" ng-disabled="myForm.$invalid" />
  <input type="button" value="Debug" ng-click="model.debug()" />
  </form>
  <script src="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系列]

http://www.darkthread.net/kolab/labs/default.aspx?m=post&t=angularjs

Comments

# by HamielKuo

黑暗大人~~ 關於驗證這塊,之前我是透過[http://blog.darkthread.net/post-2011-07-27-unobtrusive-jquery-validation.aspx]與Kendo 的alert去做結合. 不過現在專案要導入Angularjs,如果時程來的及,是否驗證這塊就交給angularjs去執行? 哈~我想這樣比較乾脆,至於Kendo 本身的validate 套件,我是沒有考慮過~

# by Jeffrey

to HamielKuo,目前手邊NG專案的驗證呈現規格特殊,評估之下,最後也沒用Angular的內建檢核,而是自己寫。 但如果規格相去不遠,我會優先考慮文中的做法。至於Kendo的Validate套件,跟你一樣,不在我的清單上。 XD

Post a comment