openplanning

Hướng dẫn và ví dụ AngularJS Validation

  1. Tổng quan
  2. ng-required
  3. ng-minlength, ng-maxlength
  4. ng-pattern
  5. ng-submitted
  6. ng-messages
  7. Tùy biến Validation

1. Tổng quan

AngularJS cung cấp một danh sách các Directive, nó giúp bạn chứng thực (validate) thông tin mà người dùng nhập vào các trường (field) của Form.
ng-required
Sét thuộc tính required (cần thiết) cho một trường đầu vào.
ng-minlength
Sét thuộc tính minlength cho một trường đầu vào.
ng-maxlength
Sét thuộc tính maxlength cho một trường đầu vào. Sét đặt giá trị cho thuộc tính này là một số âm hoặc không phải là một số, nó sẽ cho phép người dùng nhập vào nội dung với độ dài bất kỳ.
ng-pattern
Thiết lập một biểu thức chính quy (Regular expression), người dùng nhập vào nội dung phải khớp (match) với biểu thức này.
$pristine
(Trạng thái nguyên sơ) Trả về true nếu người dùng chưa tương tác với control (Chưa chạm vào nó hoặc đã chạm vào nhưng chưa từng thay đổi nó), ngược lại trả về false.
$dirty
Là trạng thái phủ định của $pristine. Chính xác là $dirty == !pristine. Trả về true nếu người dùng đã thay đổi giá trị của control ít nhất một lần.
$touched
Trả về true nếu người dùng đã từng chạm (touched) vào control này, và đã từng thoát ra khỏi nó ít nhất một lần. (Mất focus ít nhất 1 lần)
$untouched
Là trạng thái phủ định của $touched. Chính xác là $untouched == !touched. Trả về true nếu người dùng chưa từng chạm vào control này, hoặc đã chạm vào nhưng chưa từng thoát ra khỏi nó. (Chưa từng mất focus)
$error
Một đối tượng $error chứa tất cả các thuộc tính chứng thực (validation attributes) được áp dụng cho một phần tử cụ thể.
$valid
Trả về true nếu nội dung hợp lệ.
$invalid
Trả về true nếu nội dung không hợp lệ.
$pristine
Phần tử control có trạng thái $pristine = true (Trạng thái nguyên sơ) nếu người dùng chưa từng chạm vào nó, hoặc đã chạm vào nó nhưng chưa từng thay đổi nó. Ngược lại $pristine= false.
$dirty
$dirty là phủ định của $pristine, hoặc chính xác là $dirty == !$pristine. Phần tử control có trạng thái $dirty = true nếu người dùng đã thay đổi nó ít nhất 1 lần. Ngược lại trạng thái $dirty = false.
$touched & $untouched
Một Control có trạng thái $untouched nếu người dùng chưa từng chạm vào nó, hoặc chạm vào nó nhưng chưa từng thoát ra khỏi nó (Chưa từng mất focus lần nào).
Ngược lại, control có trạng thái $touched nếu người dùng đã từng chạm vào nó, và đã thoát ra khỏi nó ít nhất 1 lần (Mất focus ít nhất một lần).

2. ng-required

ng-required là một thuộc tính áp dụng cho một trường (field) đầu vào của Form để yêu cầu người dùng phải nhập nội dung cho trường này.
<input ng-model="something" ng-required="true" />

<input ng-model="something" ng-required="someLogicExpression" />
Dưới đây là một ví dụ đơn giản sử dụng ng-required, thông báo lỗi sẽ hiển thị nếu trường đầu vào không có nội dung.
ng-required-example.html
<!DOCTYPE html>
<html>
   <head>
      <title>AngularJS Validation - ng-required</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
      <script src="ng-required-example.js"></script>
      <style>
         .error-msg {
         font-size: 90%;
         font-style: italic;
         color: red;
         }
      </style>
   </head>
   <body>
      <div ng-app="myApp" ng-controller="myCtrl">
         <h3>Validation Directive: ng-required</h3>
         <p>Enter Your Name:</p>

         <form name="myForm">
            Full Name <br/>
            <input type="text"
               name="myFullName" ng-model="fullName" ng-required ="true" />
            <span ng-show="myForm.myFullName.$invalid" class="error-msg">
            You must enter your Name.
            </span>
         </form>
      </div>
   </body>
</html>
ng-required-example.js
var app = angular.module("myApp", []);

app.controller("myCtrl", function($scope) {

    $scope.fullName = "";

});
Example 2:
Một ví dụ khác với ng-required, một checkbox sẽ quyết định người dùng có phải nhập dữ liệu vào một trường cụ thể nào đó hay không.
ng-required-example2.html
<!DOCTYPE html>
<html>
   <head>
      <title>AngularJS Validation - ng-required</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
      <script src="ng-required-example2.js"></script>
      <style>
         .error-msg {
         font-size: 90%;
         font-style: italic;
         color: red;
         }
      </style>
   </head>
   <body>
      <div ng-app="myApp" ng-controller="myCtrl">
         <h3>Validation Directive: ng-required</h3>
         <p>Enter User Name:</p>
         <form name="myForm">
            <input type="checkbox" ng-model="autoName" /> Auto Name?
            <br/>
            User Name
            <br/>
            <input type="text"
               name="myUserName" ng-model="userName" ng-required ="!autoName" />
            <span ng-show="myForm.myUserName.$invalid" class="error-msg">
            Please Enter User Name.
            </span>
         </form>
      </div>
   </body>
</html>
ng-required-example2.js
var app = angular.module("myApp", []);

app.controller("myCtrl", function($scope) {

    $scope.autoName = false;
    $scope.userName = "";

});

3. ng-minlength, ng-maxlength

ng-minlength là thuộc tính áp dụng cho một trường đầu vào của Form để chỉ định số ký tự tối thiểu mà người dùng phải nhập vào trường. Chẳng hạn ng-minlength = "3" nghĩa là người dùng phải nhập ít nhất 3 ký tự vào trường này. Trong khi đó ng-maxlength chỉ định số ký tự tối đa mà người dùng được phép nhập vào một trường.
minmax-length-example.html
<!DOCTYPE html>
<html>
   <head>
      <title>AngularJS Validation</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
      <script src="minmax-length-example.js"></script>
      <style>
         .error-msg {
         font-size: 90%;
         font-style: italic;
         color: red;
         }
      </style>
   </head>
   <body>
      <div ng-app="myApp" ng-controller="myCtrl">
         <h3>Validation Directive: ng-minlength, ng-maxlength</h3>
         <p>Enter Password:</p>

         <form name="myForm" action="" ng-submit="checkOnSubmit($event)">
            Password <br/>
            <input type="password"
               name="myPassword" ng-model="password"
               ng-minlength= "5" ng-maxlength= "10" ng-required="true"/>
               
            <span ng-show="myForm.myPassword.$invalid" class="error-msg">
                 Password must be minimum 5 and maximum 10 characters
            </span>
            <br/>
            <button type="submit" >Submit</button>
         </form>
      </div>
   </body>
</html>
minmax-length-example.js
var app = angular.module("myApp", []);

app.controller("myCtrl", function($scope) {

    $scope.password = "";

    // Show more error infos.
    function printErrorInfo() {
        console.log($scope.myForm.$error);
        if ($scope.myForm.$error.minlength) {
            console.log('$error.minlength? ' + $scope.myForm.$error.minlength[0].$invalid);
        }
        if ($scope.myForm.$error.maxlength) {
            console.log('$error.maxlength? ' + $scope.myForm.$error.maxlength[0].$invalid);
        }
    }

    $scope.checkOnSubmit = function(event) {
        if ($scope.myForm.$invalid) {
            alert("Something invalid!");

            printErrorInfo();

            // Cancel submit
            event.preventDefault();
            return false;
        }
        alert("All valid => Submit now!");
        return true;
    }

});

4. ng-pattern

ng-pattern định nghĩa một khuôn mẫu (pattern) để đảm bảo nội dung người dùng nhập vào Form phải phù hợp với khuôn mẫu đó. Giá trị của ng-pattern là một biểu thức chính quy (Regular expression).
ng-pattern-example.html
<!DOCTYPE html>
<html>
   <head>
      <title>AngularJS Validation ng-pattern</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
      <script src="minmax-length-example.js"></script>
      <style>
         .error-msg {
         font-size: 90%;
         font-style: italic;
         color: red;
         }
      </style>
   </head>
   <body>
      <div ng-app="myApp" ng-controller="myCtrl">
         <h3>Validation Directive: ng-pattern</h3>
         <p>Enter Pin Code:</p>
         <form name="myForm" action="" ng-submit="checkOnSubmit($event)">
            Pin Code:<br/>
            <!-- Only Numbers Allowed, Maximum 5 Characters -->
            <input type="text" name="myPinCode" ng-model="pinCode" ng-pattern="/^[0-9]{1,5}$/" ng-required="true" />
            <span class="error-msg" ng-show="myForm.myPinCode.$error.required">Required!</span>
            <span class="error-msg" ng-show="myForm.myPinCode.$dirty && myForm.myPinCode.$error.pattern">
            Only Numbers Allowed, Maximum 5 Characters
            </span>
            <br/>
            <button type="submit" >Submit</button>
         </form>
      </div>
   </body>
</html>
ng-pattern-example.js
var app = angular.module("myApp", []);

app.controller("myCtrl", function($scope) { 
    $scope.pinCode = "";
    // Show more error infos.
    function printErrorInfo() {
        console.log($scope.myForm.$error);
    }
    $scope.checkOnSubmit = function(event) {
        if ($scope.myForm.$invalid) {
            alert("Something invalid!");

            printErrorInfo();

            // Cancel submit
            event.preventDefault();
            return false;
        }
        alert("All valid => Submit now!");
        return true;
    }
});

5. ng-submitted

AngularJS 1.3 cũng giới thiệu một property mới cho Form$submitted để biểu thị Form đã từng được submit hay chưa.
<div ng-if="myForm.$submitted">
    <!-- show errors -->
</div>
ng-submitted-example.html
<!DOCTYPE html>
<html>
   <head>
      <title>AngularJS Validation $sumitted</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
      <script src="$submitted-example.js"></script>
      <style>
         .error-msg {
         font-size: 90%;
         font-style: italic;
         color: red;
         }
      </style>
   </head>
   <body>
      <div ng-app="myApp" ng-controller="myCtrl">
         <h3>$sumitted</h3>
         <p><a href="?refresh">Reset</a></p>
         <p style="color:blue;">Click Submit button to test $sumitted</p>
         <h3 style= "color:red;">$submitted = {{myForm.$submitted}}</h3>
         <!--
            (IMPOTANT!!) To test with $submitted
            You need to remove the action attribute in the FORM.

            novalidate: Disable browser default validation.
            -->
         <form name="myForm" ng-submit="myForm.$valid && doSubmitForm($event)" novalidate>
            <input type="text" name="myField1" ng-model="field1" ng-required="true"/>
            <span ng-show="myForm.myField1.$invalid" class="error-msg">Required!!</span>
            <br/>
            <button type="submit">Submit</button>
            <h4 ng-show="myForm.$submitted && myForm.$invalid" class="error-msg">
               Something invalid, please check and re-submit
            </h4>
         </form>
      </div>
   </body>
</html>
ng-submitted-example.js
var app = angular.module("myApp", []);

app.controller("myCtrl", function($scope) {

    $scope.field1 = "";

    $scope.doSubmitForm = function(event) {
        alert("OK: " + $scope.myForm.$submitted);
        // Code to Submit form!
    }

});

6. ng-messages

Việc chứng thực (validate) Form luôn là một nhiệm vụ phức tạp và khó hiểu trong AngularJS. Vì vậy AngularJS 1.3 giới thiệu một vài cải tiến, trong đó nó giới thiệu thêm 2 Directive: ngMessages & ngMessage.
Nếu một control cần phải chứng thực (validate) trên nhiều khía cạnh, bạn cần phải thiết lập nhiều thông báo lỗi ứng với mỗi khía cạnh. Về cơ bản code của bạn sẽ giống dưới đây, và kết luận rằng nó khá dài và không thân thiện.
<div>
    <div ng-if="myForm.myFieldName.$error.required">Required Message</div>
    <div ng-if="myForm.myFieldName.$error.minlength">Min length Error Message</div>
    <div ng-if="myForm.myFieldName.$error.customValidator">Custom Error Message</div>
    <div ng-if="myForm.myFieldName.$error.asyncValidator">Custom Async Error Message</div>
    <div ng-if="myForm.myFieldName.$pending">Fetching Data...</div>
</div>

<!-- Or -->

<div>
    <div ng-show="myForm.myFieldName.$error.required">Required Message</div>
    <div ng-show="myForm.myFieldName.$error.minlength">Min length Error Message</div>
    <div ng-show="myForm.myFieldName.$error.customValidator">Custom Error Message</div>
    <div ng-show="myForm.myFieldName.$error.asyncValidator">Custom Async Error Message</div>
    <div ng-show="myForm.myFieldName.$pending">Fetching Data...</div>
</div>
Giải pháp tốt hơn là bạn nên sử dụng ng-messages & ng-message:
<div ng-messages="myForm.myFieldName.$error">
    <div ng-message="required">Required Message</div>
    <div ng-message="minlength">Min length Error Message</div>
    <div ng-message="customValidator">Custom Error Message</div>
    <div ng-message="asyncValidator">Custom Async Error Message</div>
    <div ng-message-default="asyncValidator">Some thing error</div>
</div>

<div ng-if="myForm.myFieldName.$pending">Fetching Data...</div>
Cách sử dụng tổng quát:
Usage
<!-- Using attribute directives -->
<!-- ng-messages-multiple: Optional attribute -->
<ANY ng-messages="expression" role="alert" [ng-messages-multiple]>
  <ANY ng-message="stringValue">...</ANY>
  <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
  <ANY ng-message-exp="expressionValue">...</ANY>
  <ANY ng-message-default>...</ANY>
</ANY>

<!-- Or by using element directives -->
<!-- multiple: Optional attribute -->
<ng-messages for="expression" role="alert" [multiple]>
  <ng-message when="stringValue">...</ng-message>
  <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
  <ng-message when-exp="expressionValue">...</ng-message>
  <ng-message-default>...</ng-message-default>
</ng-messages>
Chú ý: Để sử dụng ngMessages bạn phải có thư viện angular-messages.js:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-messages.js"></script>

<!-- Example: -->

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular-messages.js"></script>
Và nhập khẩu module "ngMessages" vào Apps của bạn.
// Import ngMessages module to your App.
var app = angular.module("myApp", ["ngMessages"] );
ng-messages-example.html
<!DOCTYPE html>
<html>
   <head>
      <title>AngularJS Validation</title>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
      <!-- angular-messsages.js Library -->
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular-messages.js"></script>
      <script src="ng-messages-example.js"></script>
      <style>
         .error-msg {
          font-size: 90%;
          font-style: italic;
          color: red;
         }
      </style>
   </head>
   <body>
      <div ng-app="myApp" ng-controller="myCtrl">
         <h3>Validation Directive: ng-messages, ng-message</h3>
         <p>Enter Password:</p>
         <form name="myForm" action="" ng-submit="checkOnSubmit($event)">
            Password <br/>
            <input type="password"
               name="myPassword" ng-model="password"
               ng-minlength= "5" ng-maxlength= "10" ng-required="true"/>

            <div ng-messages="myForm.myPassword.$error" ng-messages-multiple class="error-msg">
               <div ng-message="required">Required!</div>
               <div ng-message="minlength">Min length 5 characters</div>
               <div ng-message="maxlength">Max length 10 characters</div>
               <div ng-message="customValidator">Custom Error Message</div>
               <div ng-message="asyncValidator">Custom Async Error Message</div>
            </div>

            <br/>
            <button type="submit" >Submit</button>
         </form>
      </div>
   </body>
</html>
ng-messages-example.js
// Import ngMessages module to your App.
var app = angular.module("myApp", ["ngMessages"] );

app.controller("myCtrl", function($scope) {

    $scope.password = "";

    $scope.checkOnSubmit = function(event) {
        if ($scope.myForm.$invalid) {
            alert("Something invalid!");
            // Cancel submit
            event.preventDefault();
            return false;
        }
        alert("All valid => Submit now!");
        return true;
    }

});

7. Tùy biến Validation

  • Tùy biến AngularJS Validation