在使用mvc做項目時,針對應用時常遇問題,發現一個問題:當使用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 :
<! DOCTYPE html > < html > < head > < title > mvc3中使用unobtrusive時,ajax更新加載頁面后驗證失效解決方法 </ title > < script src ="jQuery/jquery-1.6.2.js" type ="text/javascript" > </ script > <script src= "jquery.validate/1.8.1/jquery.validate.js" type= "text/javascript" > </ script > <script src= "jquery.validate.unobtrusive.js" type= "text/javascript" > </ script > <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,此一解決方案也一並提供大家參考。