使用jQuery.validate.unobtrusive.js

Unobtrusive Javascript是一種將Javascript從HTML結構抽離的設計概念(延伸閱讀: kewang, ericsk),避免在HTML標籤中夾雜onchange、onclick Attribute掛載Javascript事件,讓HTML歸HTML、Javascript歸Javascript,功能權責清楚區分,HTML也變得清爽容易閱讀。

ASP.NET MVC 3加入的Unobtrusive jQuery Validation,徹底實踐了Unobtrusive Javascript的精神,透過在<input>加上data-val-*等HTML5相容Attribute註記,不需額外撰寫Javascript程式就能為欄位加上客戶端驗證邏輯。

手邊的專案一時半刻還無法都轉成ASP.NET MVC3,但又想學習這種Client Validation的優雅寫法,該怎麼辦? 搞懂jquery.validate.unobtrusive.js的原理,只要在HTML中加入適當的Attribute,我們也能實現不沾手的客戶端驗證寫法。

Brad Wilson有篇詳細的Unobtrusive Client Validation in ASP.NET MVC 3介紹,參考該文章及jquery.validate.unobtrusive.js原始碼,我將手動引用的重點整理如下:

  1. 參照jquery.js、jquery.validate.js、jquery.validate.unobtrusive.js (可透過Microsoft Ajax CDN提供)。
  2. <input>元素加上data-val=”true”,註明要啟用客戶端驗證。data-val-rulename=”驗證失敗訊息"則為<input>加上各式的規則,例如: data-val-required="姓名欄位不可空白"。
  3. 有些驗證規則需要額外參數,則可透過data-val-rulename-parameterName方式指定,例如: data-val-length-max=”60”。
  4. 在<input>後方加上<span data-valmsg-for=”inputName” data-valmsg-replace=”true/false”></span>標註顯示錯誤訊息的位置 。
  5. 如果錯誤訊息要採彙總顯示,則放入一個<div data-valmsg-summary="true"></div>

以下範例一口氣把Unobtrusive jQuery Validation內建支援的檢核規則(未包含creditcard及remote)整理在同一個網頁中,可做為應用時的參考。另外,這套檢核機制底層採用的是頗受歡迎的jQuery Validation Plugin,可視需求輕鬆加入自訂的檢核邏輯,擴充性很好,不用怕被奇怪的專案需求考倒,大家可安心服用。

<!DOCTYPE html>
<html>
<head>
    <title>jQuery Validate Unobtrusive</title>
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.js" 
     type="text/javascript"></script>   
    <script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.8.1/jquery.validate.js" 
     type="text/javascript"></script>   
    <script src="http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.js" 
     type="text/javascript"></script>   
    <style type="text/css">
body,input { font-size: 9pt; }     
.input-validation-error { border: 1px solid #ff0000 }
.input-validation-valid  { border: 1px solid #00ff00 }
.field-validation-error { color: #ff0000 }
.field-validation-valid { display: none }
.validation-summary-errors { font-weight: bold; color: #ff0000 }
.validation-summary-valid { display: none }
    </style>
</head>
<body>
<form id="form1" method="get">
    <div data-valmsg-summary="true"><ul></ul></div>
    <div>
    <input type="text" id="tReq" name="tReq" data-val="true" 
     data-val-required="不可空白"/>
    <span data-valmsg-for="tReq"></span>
    </div>
    <div>
    <input type="text" id="tAccept" name="tAccept" value="a.doc" 
     data-val="true" data-val-accept="檔名須為.jpg、.gif或.png"
     data-val-accept-exts="jpg|gif|png"
     />
    <span data-valmsg-for="tAccept"></span>
    </div>
    <div>
    <input type="text" id="tRegex" name="tRegex" value="123-ABC@"
     data-val="true" data-val-regex="車牌格式須為999-999"
     data-val-regex-pattern="[0-9A-Z]{3}-[0-9A-Z]{3}"
     />
    <span data-valmsg-for="tRegex"></span>
    </div>
    <div>
    <input type="text" id="tDigit" name="tDigit" value="-1234"
     data-val="true" data-val-digits="只接受數字字元"/>
    <span data-valmsg-for="tDigit"></span>
    </div>
    <div>
    <input type="text" id="tNum" name="tNum" value="-1,234.56A"
     data-val="true" data-val-number="必須為有效數字"/>
    <span data-valmsg-for="tNum"></span>
    </div>
    <div>
    <input type="text" id="tDate" name="tDate" value="X/01/X2000"
     data-val="true" data-val-date="必須為日期(僅粗略檢查)"/>
    <span data-valmsg-for="tDate"></span>
    </div>
    <div>
    <input type="text" id="tEmail" name="tEmail" value="jeffrey @mail.com"
     data-val="true" data-val-email="必須為Email"/>
    <span data-valmsg-for="tEmail"></span>
    </div>
    <div>
    <input type="text" id="tUrl" name="tUrl" value="http:// blog2.darkthread.net"
     data-val="true" data-val-url="必須為有效網址"/>
    <span data-valmsg-for="tUrl"></span>
    </div>
    <div>
    <input type="text" id="tLen" name="tLen" value="TTT"
     data-val="true" data-val-length="長度須介於4到8之間"
     data-val-length-min="4" data-val-length-max="8"
     />
    <span data-valmsg-for="tLen"></span>
    </div>
    <div>
    <input type="text" id="tRange" name="tRange" value="5"
     data-val="true" data-val-range="須介於10到100" 
     data-val-range-min="10" data-val-range-max="100"
     />
    <span data-valmsg-for="tRange"></span>
    </div>
    <div>
    <input type="text" id="tEq" name="tEq" value="99"
     data-val="true" data-val-equalto="必須與上方欄位內容相同"
     data-val-equalto-other="tRange"
     />
    <span data-valmsg-for="tEq"></span>
    </div>
    <div>
    <input type="submit" id="send" value="Send" />
</form>
</body>
</html>

PS: Unobtrusive jQuery Validation一樣可以搭配先前介紹過的"內嵌式錯誤訊息顯示"。

歡迎推文分享:
Published 27 July 2011 06:52 AM 由 Jeffrey
Views: 83,220



意見

# mrkt said on 26 July, 2011 08:00 PM

這篇雖然說的是jQuery的plug-in,

但我看到的是「Unobtrusive Javascript」這個觀念,

這也是我一直以來的堅持,html與不混合,行為與結構的分離,

頂多只在html裡開個js的入口,傳遞動態產生的參數給js檔使用,

如 Url.Action, 這也是以前同事教我的手法,

希望黑大的這篇文章,可以給更多網頁程式開發人員帶來硬想與改變.

# Leo said on 27 July, 2011 12:02 AM

收下了,謝謝黑大。

# arthas said on 13 October, 2011 10:38 PM

您好,想請教在此提交表單驗証是使用submit

若是單純想使用button需由哪呼叫呢 XD

感恩

   <script type="text/javascript">

       $(document).ready(function () {

           $("#Button1").click(function () {

               $("#aspnetForm").??();

       });

   });

   </script>

# Jeffrey said on 14 October, 2011 02:06 AM

to arthas, 可寫成if ($("#form1").valid()) { ... }

PS: 但若是涉及遠端檢核,可能就得處理檢核結果以非同步方式傳回的時間差,寫法要再複雜一點

# arthas said on 14 October, 2011 06:06 AM

謝謝黑大的幫忙

使用以上的方式可以檢核了,但有一個部份較為奇怪

使用您的範例

data-valmsg-for 或 data-valmsg-summary 都可正確顯示

但目前要套用的頁面是 masterpage中Content頁就無法顯示

再測試一下把原先要套用的頁面不使用masterpage又能顯示

找了好久不知道什麼原因,不知道該從何下手

所以又來麻煩黑大了

# Jeffrey said on 14 October, 2011 08:06 AM

to arthas,使用MasterPage時,input的name及id會被加料,例如: ctl00_ContentPlaceHolder1_TextBox1,若你的data-valmsg-for只寫"TextBox1"就會因為對不上無法顯示。可以透過從Server端將ClientID帶入HTML的做法克服(補充: blog2.darkthread.net/.../1445.aspx),或是用jQuery在載入時搜尋input name動態產生也是一種解法。

# arthas said on 17 October, 2011 01:30 AM

感恩 謝謝黑大

確實是masterpage name加料的問題,有參考了您的文章。

但要再標籤內再call javascript 總覺得又繞了一圈

所以現在就直接先寫死像是

<span data-valmsg-for="ctl00$cphMain$TB2"></span>

雖然有點醜 XD

不過覺得有些奇怪jquery.validate.js怎麼是用 name來做data-valmsg-for 而不是用id  @@? 不解

# Jeffrey said on 17 October, 2011 06:31 AM

to arthas, 我自己的專案裡主要都改用內嵌式顯示(blog2.darkthread.net/post-2011-07-04-asp-net-mvc-inline-validation-chinese.aspx) ,在makeValidationInline()時會自動找到name補上<span data-valmsg-for="...">,算是逃避了這個惱人問題。

# Song said on 13 May, 2014 01:31 AM

您好,想請問是否有使用過於"動態產生"的input type="text"標籤?

我在View中有一個<input type="text">標籤,使用@Html.TextBoxFor方法產生的,所以擁有驗證功能。

若是改手動KEY如:

<input type="text" id="txt1" name="[0].txt" data-val="true" data-val-required="txt 欄位是必要項。"  />

也有驗證功能。

但是使用JQuery產生的<input type="text">不能驗證,且有加上如

data_val="true"

data_val_required="欄位是必要項。"

就不含有驗證功能了...

# Jeffrey said on 13 May, 2014 03:43 AM

to Song, 動態產生輸入元素或修改data-val-*後,需要重新執行$.validator.unobtrusive.parse(...)才會生效。參考: stackoverflow.com/.../unobtrusive-validation-not-working-with-dynamic-content (也可考慮文中提到的Plugin)

# Song said on 13 May, 2014 05:26 AM

To Jeffrey ,問題解決了!謝謝您

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<July 2011>
SunMonTueWedThuFriSat
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456
 
RSS
創用 CC 授權條款
【廣告】
twMVC
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication