June 29, 2013

KnockoutJS - 使用Knockout Validation實作前端資料驗證

在設計表單頁面時,使用者送出表單資料前,我們一定會為使用者所填入的資料做第一階段的驗證,以避免資料送到後端時不符合預期格式或是不正確的數值。Knockout ValidationKnockout最有名的extender之一,即是為了前端資料驗證使用。關於extender的實作,可參考Knockout官方文件Using extenders to augment observables,在此不詳述。

Knockout Validation內建提供了十幾種驗證規則,可驗證資料是否為必填、是否為Email格式或是特定字串格式等。除此之外開發人員也可自訂驗證規則或是直接套用熱心網友提供的驗證規則

本篇文章將以一個簡單的表單範例來說明如何使用Knockout Validation實作前端資料驗證。表單頁面如下


從上圖可以看到使用者需要輸入的欄位有4個,Email、Password、Confirm Your Password及Name。輸入完畢後按下Register按鈕送出資料,Knockout Validation則是在按下Register按鈕後進行資料驗證。針對表單資料的驗證需要完成以下需求:
  1. Email欄位為必填,且格式需符合正確的Email格式,如pete.chen@outlook.com
  2. Password欄位為必填,長度為8到16個字元,字元至少需包含1個大寫英文字母、1個小寫英文字母及1個數字,如Passw0rd
  3. Confirm Your Password欄位為必填,且需與Password欄位資料相同
  4. Name欄位為必填,長度為2到30個字元。

建立ViewModel
function ViewModel() {

    var self = this;

    self.Email = ko.observable().extend({
        required: true,
        email: true
    });

    self.Password = ko.observable().extend({
        required: true,
        pattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,16}$/
    });

    self.Password2 = ko.observable().extend({
        required: true,
        equal: self.Password
    });

    self.Name = ko.observable().extend({
        required: true,
        minLength: 2,
        maxLength: 30
    });

    self.Register = function () {

        self.errors = ko.validation.group(self);

        if (self.isValid()) {
            alert('data sent');
        } else {
            self.errors.showAllMessages();
        }
    };
}

ko.validation.configure();
ko.applyBindings(new ViewModel());


ViewModel內實作了4個observable屬性(Email、Password、Password2和Name)及1個方法(Register)。以下針對ViewModel的實作做說明:
  1. 5~8行:設定Email屬性的驗證規則,使用required定義屬性必需要有資料,email定義資料格式為Email格式
  2. 10~13行:設定Password屬性的驗證規則,使用required定義屬性必需要有資料,pattern定義資料格式需符合正則表示式^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,16}$。這裡要注意的是pattern的設定方式有兩種,一種是將正則表示式以斜線(/)包起來,如程式碼中的/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,16}$/,另一種則是以字串的方式將正則表示式放在單雙引號中,但若引號中含有反斜線(\),則需將其取代為兩個反斜線,如'^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,16}$'
  3. 15~18行:設定Password2屬性的驗證規則,使用required定義屬性必需要有資料,equal定義資料需與Password屬性相同
  4. 20~24行:設定Name屬性的驗證規則,使用required定義屬性必需要有資料,minLength定義資料長度最小2個字元,maxLength定義資料長度最多30個字元
  5. 26~36行:為一函式,其中28行執行資料驗證,並將驗證結果指派給errors屬性。這裡要注意的是,Knockout Validation在驗證ViewModel時,預設只會驗證第一層的屬性。也就是說如果某個屬性本身是個複雜物件(complex object),則其底下的屬性將不會被驗證。若想將完整地驗證ViewModel,可設定deep參數,如ko.validation.group(self, { deep: true });。30行使用isValid()來判斷ViewModel的驗證是否成功,若失敗則在33行執行self.errors.showAllMessages();將驗證錯誤訊息顯示在頁面上,預設訊息會顯示在驗證失敗的欄位右側,如

  6. 38行:完成Knockout Validation設定,例如設定錯誤訊息或欄位的顯示樣式等。在此使用預設設定,詳細說明可參考Knockout Validation Wiki上的Configuration Options

設定View的data bindings
<div>Registration Form</div>
<div>Email:
    <input type="text" data-bind="value: Email" />
</div>
<div>Password:
    <input type="text" data-bind="value: Password" />
</div>
<div>Confirm Your Password:
    <input type="text" data-bind="value: Password2" />
</div>
<div>Name:
    <input type="text" data-bind="value: Name" />
</div>
<div>
    <input type="button" value="Register" data-bind="click: Register" />
</div>

View的設定相對ViewModel簡單多了,在這裡僅僅使用到了valueclick binding

執行結果



自訂錯誤訊息

在未做任何設定下,Knockout Validation將會顯示預設的錯誤訊息,若想顯示自訂的錯誤訊息,可在ViewModel屬性中加入message參數,如
self.Email = ko.observable().extend({
    required: {
        params: true,
        message: "Please enter your email"
    },
    email: {
        params: true,
        message: "The format is not correct"
    }
});
上面程式碼中的message參數即為自訂訊息,要注意的是驗證規則的設定值改為指派給params參數。如需更進階的自訂錯誤訊息方式,可參考Knockout Validation Wiki上的Validation Bindings

No comments: