[angularjs入門]ng-submit and ngMessage(1.3之後的驗證)

angularjs入門-ng-submit and ngMessage(1.3之後的驗證)

前言

 

 

這一篇我還是會需要先建立一些db資料,但就是一個簡單的帳號註冊功能,在$http有帶到簡單的code first建立db的過程,這篇只會簡單的帶一下建立db的部份,不會再詳細的去帶到detail的部份,如果有疑問的話,可以去看一下angularjs入門-$http,ng-submit就是搭配了驗證功能,所以我們只要需要驗證功能,我們就需要用到這個directive,ngMessage則是1.3之後簡化了angularjs很繁雜的驗証功能的寫法,在此我還是先從db的資料建立開始做起,還是拿之前的student來做table範例,程式碼修改如下

using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Migrations;

namespace WebApiDemo.Models
{
    public class DefaultDataInit:DropCreateDatabaseAlways<DefaultContext>
    {
        public override void InitializeDatabase(DefaultContext context)
        {
            base.InitializeDatabase(context);
            var student = new List<Student>()
            {
                new Student() { Name = "王小明", PhoneNumber = "0915808888", Address = "台中市",Password="1234" },
                new Student() { Name = "王大明", PhoneNumber = "0915801111", Address = "台北市",Password="1234"  },
                new Student() { Name = "王大雄", PhoneNumber = "0915806666", Address = "台南市",Password="1234"  },
                new Student() { Name = "王小雄", PhoneNumber = "0915800000", Address = "新北市",Password="1234"  },
                new Student() { Name = "王小安", PhoneNumber = "0915807777", Address = "桃園市",Password="1234"  }
            };
            context.Student.AddRange(student);
            context.SaveChanges();
        }

      
    }
}
 <connectionStrings>
    <add name="DefaultConnection" connectionString="data source=(LocalDb)\MSSQL;initial catalog=NgMessage;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
  </connectionStrings>

 

其餘過程在之前已經提過,就不再多做說明

 

1.3之前驗證的做法

 

其實在1.3之前,驗證的寫法是有點麻煩的,程式碼如下圖示例

 

image

 

那1.3之後的寫法就變得簡潔和易讀許多,先給個1.3之後的比較圖示例,細節會留在之後再陳述

 

image

 

驗證的一些可用功能

 

我們可以看到上面的程式碼,但其實這有些問題,我們期望的是在輸入值之後,有錯誤才顯示出來,但這邊卻是會先把錯誤顯示出來了,如下圖

 

image

 

這時候我們必須先了解一下,有關於可使用的一些驗證功能

 

  1. 必填:<input type="text" ng-model="name" required>
  2. 最小長度:<input type="text" ng-model="name" ng-minlength="3">
  3. 最大長度:<input type="text" ng-model="name" ng-maxlength="12">
  4. 正規表達式:<input type="text" ng-model="name" ng-pattern="/[0-9]/">
  5. 數字:<input type="number" ng-model="age">
  6. Email:<input type="email" ng-model="email">
  7. Url:<input type="url" ng-model="url">
  8. Date:<input type="date" ng-model="date"

 

然後是對應的可以取得驗證狀態,也就是如果有錯誤的話,會為true

 

  1. formName.inputName.$error.required
  2. formName.inputName.$error.minlength
  3. formName.inputName.$error.maxlength
  4. formName.inputName.$error.pattern
  5. formName.inputName.$error.number
  6. formName.inputName.$error.email
  7. formName.inputName.$error.url
  8. formName.inputName.$error.date

 

再來就是驗證狀態了,比如說我們想檢查是否有通過驗證,或是否未輸入的狀態,如果符合條件的話,會為true

 

  1. 通過驗證: $valid
  2. 未通過驗證: $invalid
  3. 該欄位未曾輸入值: $pristine
  4. 該欄位已曾輸入值: $dirty

 

ngMessage部份

 

如何開始使用ngMessage呢?我們必須要先在頁面加入 <script src="~/Scripts/angular-messages.js"></script>,還有必須在後端加入ngMessages,因為我是用.net mvc,所以我把會共用的放在_Layout.cshtml,以下是所有的程式碼

_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>ngMessage範例</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body ng-app="MyApp">
    <div class="container body-content">
        @RenderBody()
    </div>
        <script src="~/Scripts/angular.js"></script>
    <script src="~/Scripts/angular-messages.js"></script>
    @RenderSection("scripts", required: false)
</body>
</html>

 

Index.js

angular.module('MyApp', ['ngMessages']) //這邊需要加入ngMessages
    .controller('FirstCtrl', function ($scope, $http) {
        var url = 'http://localhost:58973/Api/Values';
        $http.get(url).success(function (data) {
            $scope.students = data;
        });
    });

 

Index.cshtml

<div ng-controller="FirstCtrl">
    <div class="row">
        @*必須得加入name的名稱,還有ng-submit跟novalidate*@
        <form name="myForm" ng-submit="submit()" novalidate> 
            @*必須得加入name的名稱,驗証是以此名稱做依據*@
            Name:<input type="text" name="name" ng-model="Add.Name" class="form-control" required ng-minlength="3" />
            @*最外層加上ng-show是為了不想在未輸入值之前,就預先顯示錯誤訊息*@
            <div ng-messages="myForm.name.$error" ng-show="myForm.name.$dirty">
                <p ng-message="required">Name必填</p>
                <p ng-message="minlength">最少三碼</p>
            </div>
            Password:<input type="password" name="password" ng-model="Add.Password" class="form-control" required
                            ng-minlength="4" ng-maxlength="10" />
            <div ng-messages="myForm.password.$error" ng-show="myForm.password.$dirty">
                <p ng-message="required">Password必填</p>
                <p ng-message="minlength">至少輸入四碼</p>
                <p ng-message="maxlength">至多輸入十碼</p>
            </div>
            PhoneNumber:<input type="number" name="phoneNumber" ng-model="Add.PhoneNumber" class="form-control" required
                               ng-minlength="7" ng-maxlength="10" />
            <div ng-messages="myForm.phoneNumber.$error" ng-show="myForm.phoneNumber.$dirty">
                <p ng-message="required">PhoneNumber必填</p>
                <p ng-message="minlength">至少輸入七碼</p>
                <p ng-message="maxlength">至多輸入十碼</p>
                <p ng-message="number">只能輸入數字</p>
            </div>
            Address:<input type="text" name="Address" ng-model="Add.Address" class="form-control" required />
            <div ng-messages="myForm.Address.$error" ng-show="myForm.Address.$dirty">
                <p ng-message="required">Address必填</p>
            </div>
            @*ng-disabled則是如果任格一個欄位未成功,預設是不能按下送出按鈕*@
            <input type="submit" value="新增" class="btn btn-primary" ng-disabled="myForm.$invalid" />
        </form>
    </div>
    <hr />
    <div class="row">
        <table class="table">
            <tr>
                <th>姓名</th>
                <th>電話</th>
                <th>地址</th>
                <th>密碼</th>
            </tr>
            <tr ng-repeat="item in students">
                <td>{{item.Name}}</td>
                <td>{{item.PhoneNumber}}</td>
                <td>{{item.Address}}</td>
                <td>{{item.Password}}</td>
            </tr>
        </table>
    </div>
</div>
@section scripts{
    <script src="~/App/Index.js"></script>
}

 

上面我都有在每行的上面,加上一些注解說明,所以在此就不多做說明

 

驗證angularjs提供css

 

接下來討論一下有關美化驗證的部份,其實angularjs也有提供有關驗證相關的一系列樣式,如下

ng-pristine
ng-dirty
ng-valid
ng-invalid

所以我們可以加入css,讓驗證畫面看起來更直覺

image

 

image

 

 input.ng-invalid{
        border-color:red;
        border-width:2px;
    }
   input.ng-pristine{
       border-color:blue;
       border-width:2px;
   }
   .error{
       color:red;
   }

 

然後我們錯誤的div部份,需自行加入class,如下例

  <div ng-messages="myForm.name.$error" class="error" ng-show="myForm.name.$dirty">
      <p ng-message="required">Name必填</p>
      <p ng-message="minlength">最少三碼</p>
      <p ng-message="maxlength">至多輸入十碼</p>
  </div>

 

1.3之後還有加入了,如果按下submit之後,有錯誤的話,會顯示我們自行定義的css語法,如下

form.ng-submitted .ng-invalid {
        border-color: red;
        border-width: 2px;
    }

 

我們也可以在controller裡面寫驗證判斷語法,比如說我們只要確定驗證成功,我們就alert一個成功的訊息

angular.module('MyApp', ['ngMessages']) //這邊需要加入ngMessages
    .controller('FirstCtrl', function ($scope, $http) {
        var url = 'http://localhost:58973/Api/Values';
        $http.get(url).success(function (data) {
            $scope.students = data;
        });

        $scope.submit = function () {
            if ($scope.myForm.$valid) alert('成功');
            if ($scope.myForm.$invalid) alert('驗證失敗');
        }
    });

 

如果我們有很多欄位想要顯示的錯誤訊息如果一樣,我們其實還能再抽出來重覆使用,如下面程式碼是包

<script type="text/ng-template" id="commonMessage">
    <p ng-message="required">此欄位必填</p>
    <p ng-message="minlength">輸入太少</p>
    <p ng-message="maxlength">輸入太多</p>
    <p ng-message="number">只能輸入數字</p>
</script>

 

然後我們就可以在html裡面直接用下面的語法,就可以套用這段抽出來的驗證語法

 <div class="error" ng-messages="myForm.Address.$error" ng-show="myForm.Address.$dirty" ng-messages-include="commonMessage">
 </div>

 

其實我們也可以覆寫驗證裡面定義的字,比如像下面的html這樣

Address:<input type="text" name="Address" ng-model="Add.Address" class="form-control" required />
            <div class="error" ng-messages="myForm.Address.$error" ng-show="myForm.Address.$dirty" ng-messages-include="commonMessage">
                <p ng-message="required">Address必填</p> @*此行重寫了原本定義的錯誤訊息*@
            </div>

 

下面則是完整的程式碼

<style>
   form.ng-submitted .ng-invalid {
  border-color: red;
  border-width: 2px;
} 
   input.ng-pristine{
       border-color:blue;
       border-width:2px;
   }
   .error{
       color:red;
   }
   
</style>

<div ng-controller="FirstCtrl">
    <div class="row">
        @*必須得加入name的名稱,還有ng-submit跟novalidate*@
        <form name="myForm" ng-submit="submit()" novalidate> 
            @*必須得加入name的名稱,驗証是以此名稱做依據*@
            Name:<input type="text" name="name" ng-model="Add.Name" class="form-control" required ng-minlength="3" />
            @*最外層加上ng-show是為了不想在未輸入值之前,就預先顯示錯誤訊息*@
            <div ng-messages="myForm.name.$error" class="error" ng-show="myForm.name.$dirty" ng-messages-include="commonMessage">
               
            </div>
            Password:<input type="password" name="password" ng-model="Add.Password" class="form-control" required
                            ng-minlength="4" ng-maxlength="10" />
            <div ng-messages="myForm.password.$error" class="error" ng-show="myForm.password.$dirty" ng-messages-include="commonMessage">
            </div>
            PhoneNumber:<input type="number" name="phoneNumber" ng-model="Add.PhoneNumber" class="form-control" required
                               ng-minlength="7" ng-maxlength="10" />
            <div class="error" ng-messages="myForm.phoneNumber.$error" ng-messages-include="commonMessage" ng-show="myForm.phoneNumber.$dirty">

            </div>
            Address:<input type="text" name="Address" ng-model="Add.Address" class="form-control" required />
            <div class="error" ng-messages="myForm.Address.$error" ng-show="myForm.Address.$dirty" ng-messages-include="commonMessage">
                <p ng-message="required">Address必填</p> @*此行重寫了原本定義的錯誤訊息*@
            </div>
            @*ng-disabled則是如果任格一個欄位未成功,預設是不能按下送出按鈕*@
            <input type="submit" value="新增" class="btn btn-primary" ng-disabled="myForm.$invalid" />
        </form>
    </div>
    <hr />
    <div class="row">
        <table class="table">
            <tr>
                <th>姓名</th>
                <th>電話</th>
                <th>地址</th>
                <th>密碼</th>
            </tr>
            <tr ng-repeat="item in students">
                <td>{{item.Name}}</td>
                <td>{{item.PhoneNumber}}</td>
                <td>{{item.Address}}</td>
                <td>{{item.Password}}</td>
            </tr>
        </table>
    </div>
    
</div>


<script type="text/ng-template" id="commonMessage">
    <p ng-message="required">此欄位必填</p>
    <p ng-message="minlength">輸入太少</p>
    <p ng-message="maxlength">輸入太多</p>
    <p ng-message="number">只能輸入數字</p>
</script>

@section scripts{
    <script src="~/App/Index.js"></script>
}

 

接著我們也可以把統一驗證的程式碼放在另外一支html裡面共用,我這邊因為是mvc,所以我新增的是cshtml檔,可以看看最後程式碼的樣子

Index.cshtml

<style>
    input.ng-invalid {
        border-color: red;
        border-width: 2px;
    }
   input.ng-pristine{
       border-color:blue;
       border-width:2px;
   }
   .error{
       color:red;
   }
   
</style>

<div ng-controller="FirstCtrl">
    <div class="row">
        @*必須得加入name的名稱,還有ng-submit跟novalidate*@
        <form name="myForm" ng-submit="submit()" novalidate> 
            @*必須得加入name的名稱,驗証是以此名稱做依據*@
            Name:<input type="text" name="name" ng-model="Add.Name" class="form-control"
                         required ng-minlength="3"  />
            @*最外層加上ng-show是為了不想在未輸入值之前,就預先顯示錯誤訊息*@
            <div ng-messages="myForm.name.$error" class="error" ng-show="myForm.name.$dirty" ng-messages-include="/Home/template">
            </div>
            Password:<input type="password" name="password" ng-model="Add.Password" class="form-control" required
                            ng-minlength="4" ng-maxlength="10" />
            <div ng-messages="myForm.password.$error" class="error" ng-show="myForm.password.$dirty" ng-messages-include="/Home/template">
            </div>
            PhoneNumber:<input type="number" name="phoneNumber" ng-model="Add.PhoneNumber" class="form-control" required
                               ng-minlength="7" ng-maxlength="10" />
            <div class="error" ng-messages="myForm.phoneNumber.$error" ng-messages-include="/Home/template" ng-show="myForm.phoneNumber.$dirty">
            </div>
            Address:<input type="text" name="Address" ng-model="Add.Address" class="form-control" required />
            <div class="error" ng-messages="myForm.Address.$error" ng-show="myForm.Address.$dirty" ng-messages-include="/Home/template">
            </div>
            @*ng-disabled則是如果任格一個欄位未成功,預設是不能按下送出按鈕*@
            <input type="submit" value="新增" class="btn btn-primary" ng-disabled="myForm.$invalid" />
        </form>
    </div>
    <hr />
    <div class="row">
        <table class="table">
            <tr>
                <th>姓名</th>
                <th>電話</th>
                <th>地址</th>
                <th>密碼</th>
            </tr>
            <tr ng-repeat="item in students">
                <td>{{item.Name}}</td>
                <td>{{item.PhoneNumber}}</td>
                <td>{{item.Address}}</td>
                <td>{{item.Password}}</td>
            </tr>
        </table>
    </div>
</div>
<script type="text/ng-template" id="commonMessage">
    <p ng-message="required">此欄位必填</p>
    <p ng-message="minlength">輸入太少</p>
    <p ng-message="maxlength">輸入太多</p>
    <p ng-message="number">只能輸入數字</p>
</script>
@section scripts{
    <script src="~/App/Index.js"></script>
}

 

template.cshtml


    <p ng-message="required">此欄位必填</p>
    <p ng-message="minlength">輸入太少</p>
    <p ng-message="maxlength">輸入太多</p>
    <p ng-message="number">只能輸入數字</p>

 

Index.js

angular.module('MyApp', ['ngMessages']) //這邊需要加入ngMessages
    .controller('FirstCtrl', function ($scope, $http) {
        var url = 'http://localhost:58973/Api/Values';
        $http.get(url).success(function (data) {
            $scope.students = data;
        });

        $scope.submit = function () {
            if ($scope.myForm.$valid) alert('成功');
            if ($scope.myForm.$invalid) alert('驗證失敗');
        }
    });

 

這邊我一樣會附上原始碼供參考,入門部份也差不多到此告一段落,其實angularjs還有很多議題,但我認為不會屬於入門的部份,但其實掌握這些入門的部份,要做個純ajax的小網站也夠用了,在這邊我並沒有把資料真的寫進後端,有興趣的人可以自己試試看,然後把資料寫入資料庫吧,以上再多多指教。

 

https://github.com/kinanson/NgMessage-Sample