謙卑式jQuery檢核範例-動態變更檢核設定
0 |
接連介紹了謙卑式jQuery檢核、整合Server端檢核、自訂檢核條件,針對應用時常遇問題,發現還缺了一塊: 當使用AJAX方式動態更新<input>內容或檢核設定時,應如何讓檢核設定生效?
依據jquery.validate.unobtrusive.js的運作原理,它會在網頁載入後立即呼叫$.validator.unobtrusive.parse(document)解析讀取元素的data-val-*標示,完成檢核條件設定,這也意味著事後加入<input>或追加data-val-*將不會被納入表單送出前的檢核項目。Brad Wilson在文章中有一節"Parsing New HTML For Validation"提到可呼叫jQuery.validator.unobtrusive.parse()或jQuery.validator.unobtrusive.parseElement()重新解析並設定檢核條件,但經實測,除非整個<form>是動態重新產生的,否則parse()/parseElement()並無預期效果,<form>的檢核條件仍維持onload事件所讀取到的內容。
追進原始碼,發現問題出在jquery.validate.unobtrusive.js透過$("form”).validate(…)重新設定表單撿核條件,但在jquery.validate.js中,form一旦被validate()設定過,validator物件就會被保存在$(theForm).data(“validator”),之後再呼叫validate(options),會只傳回原先的validator物件,而不會將options的內容併入validator:
validate: function (options) {
// if nothing is selected, return nothing; can't chain anyway
if (!this.length) {
options && options.debug && window.console && //...省略...
return;
}
// check if a validator for this form was already created
var validator = $.data(this[0], 'validator');
if (validator) {
return validator;
}
以此推論,除非form本身尚未建立.data(“validator”),否則呼叫.validate(options)不會有任何效果。但在jquery.validate.unobtrusive.js中,網頁載入時就已對既有<form>做過.validate(),也都已建立validator物件,除非<form>為事後動態新增,parse()或parseElement()無力變更一載入時就讀取好的檢核設定。針對這個問題,我找到的解套方法是手動將$(theForm).removeData(“validator”),在下次parse()/parseElement()時便能砍掉重練。
以下是程式範例。我動態新增了一個<input id="tDyna">,並為<input id="tReq">增加data-val-number="..."數字檢核條件,程式中示範了三種寫法,並已在註解中說明用法與效果差別:
<!DOCTYPE html>
<html>
<head>
<title>Unobtrusive jQuery Validation for Dynamic Content</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>
<script type="text/javascript">
$(function () {
//tReq新增數字檢核
$("#tReq").attr("data-val-number", "須為數字(動態加上的檢核)");
//無中生有新增一個<input id=tDyna>,並加上必填檢核
var id = "tDyna";
$("#dvDyna").append("<input type='text' id='" + id + "' />");
$("#tDyna").attr({
name: id,
"data-val": "true",
"data-val-required": "不可空白(動態加上的檢核)",
}).after("<span data-valmsg-for='" + id + "' />");
//要先移除原有設定
$("#form1").removeData("validator");
//方法一,傳入新增檢核設定的元素,包含該元素的<form>會重設檢核條件
//$.validator.unobtrusive.parseElement(document.getElementById("tDyna"));
//方法二,傳入內含<input data-val="true">元素的容器selector,
//將重新解析容器內的元素的data-val-*設定,接著所有的<form>會更新檢核規則
//$.validator.unobtrusive.parse("#dvDyna");
//在本案例中方法一、二都只更新了<input id='tDyna'>。<input id='tReq'>新增的
//data-val-number並未被解析生效,我們可擴大解析範圍改善這個問題
$.validator.unobtrusive.parse("#form1"); //或parse(document)亦可
});
</script>
</head>
<body>
<form id="form1">
<div>
<input type="text" id="tReq" name="tReq"
data-val = "true" data-val-required = "不可空白" />
<span data-valmsg-for="tReq"></span>
</div>
<div id="dvDyna">
</div>
<input type="submit" value="Submit" />
</form>
</body>
</html>
值得注意的是,$(theForm).removeData(“validator”)的解法會移除原有的檢核設定,如果曾另外透過程式動態修改validator內容,移除validator將導致事後修改一併失效。針對這個缺點,XHalent提出了更優雅的解法,撰寫了一支parseDynamicContent() Plugin可將新增的檢核條件合併進原有的validator物件中,但必須多載入jQuery Plugin,此一解決方案也一併提供大家參考。
Comments
Be the first to post a comment