前陣子案子遇到的問題,是一個簡單的表單需求,使用 ASP.NET 作為伺服器端語言,而前端要使用 jQuery validate 做驗證再送出。
在送出前需要再做一些事件,所以使用 jQuery validate submitHandler 事件處理,最後再以 form.submit();
送出。
code 簡單重現如下:
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("form").validate({
onfocusout: false,
onclick: false,
onkeyup: false,
rules: {‘
txt’: {
required: true,
maxlength: 5
}
},
messages: {‘
txt’: {
required: "請輸入姓",
maxlength: "姓請勿大於 5 個字元"
}
},
showErrors: function(errorMap, errorList) {
var msg = "";
$.each(errorList, function(i, v) {
msg += ("‧" + v.message + "\r\n");
});
if (msg != "") alert(msg);
},
submitHandler: function(form) {
alert("做些事..開視窗之類的");
// jQuery 的 submit 會引發無窮迴圈,別用
//$("form").submit();
//
// jQuery validate 中會呼叫 JavaScript 原生的 submit()
form.submit();
//
// 原生的 submit
//document.getElementById("form1").submit();
}
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="txt" runat="server"></asp:TextBox>
<asp:ImageButton ID="ImageButton1" runat="server" onclick="ImageButton1_Click" />
</div>
</form>
</body>
</html>
還有 Code Behind 的部分,是 ImageButton1 的點擊事件:
protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
{
Response.Write("我是 ImageButton1 按下後引發的事件");
}
其中 submitHandler 事件:
submitHandler: function (form) {
alert('做些事..開視窗之類的');
form.submit();
}
做表單的送出前的事件處理,記得不要用 $("#form1").submit();
送出,
不然會引發無窮迴圈,一直在送出 -> 驗證 -> 送出 -> 驗證中鬼打牆,以本例來說的話就會不斷地跳 alert。
請用 form.submit();
來觸發表單送出事件,這是 jQuery validate 中呼叫 JavaScript 原生的 submit。
好了,解決了無窮迴圈的問題,但接下來我發現上面這段 Code 在 Chrome 雖一切正常,但在 IE 中就是無法引發 ImageButton1_Click
的伺服器端事件,
但確實有被 submit,畫面閃了一下。所以應該是 IE 少送了什麼東西,導致 ASP.NET 不知道是哪個控制項引發表單送出的囉?
先來一段純 HTML 來做實驗:
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("form").validate({
onfocusout: false,
onclick: false,
onkeyup: false,
rules: {‘
txt’: {
required: true,
maxlength: 5
}
},
messages: {‘
txt’: {
required: "請輸入姓",
maxlength: "姓請勿大於 5 個字元"
}
},
showErrors: function(errorMap, errorList) {
var msg = "";
$.each(errorList, function(i, v) {
msg += ("‧" + v.message + "\r\n");
});
if (msg != "") alert(msg);
},
submitHandler: function(form) {
alert("做些事..開視窗之類的");
// jQuery 的 submit 會引發無窮迴圈,別用
//$("form").submit();
//
// jQuery validate 中會呼叫 JavaScript 原生的 submit()
form.submit();
//
// 原生的 submit
//document.getElementById("form1").submit();
}
});
});
</script>
</head>
<form id="form1" action="" method="get">
<input type="text" name="txt" value="test" />
<input type="image" src="圖檔位置" />
</form>
如果用上面這段 code 去觀察的話,應該可以發現 Chrome 跟 IE 的差別,Chrome 在送出時除了 txt 的值還會附加 x 跟 y 的值,而 IE 只會有 txt 的值。
IE 只有在真的「點擊」那顆 image button 造成 submit 事件時,才會附加 x 跟 y。(如果用 ASP.NET 去做的話,就會找不到 Request.Form[“ImageButton1.x”])
上面那段 code 最後是透過 javascript 去送出表單的,而非真的點擊該 image button,因此就不會有 x 跟 y 的值了。
依照 ASP.NET PostBack 的運作機制,除了用 __doPostBack 搭配 __EVENTTARGET 判斷外,
也會判斷控制項類型 Button 或 ImageButton,若為 ImageButton 的話,還會在控制項名稱後面附加 .x 跟 .y,像是這樣:ImageButton1.x。
上述都是用以判斷是哪個控制項,接下來要引發哪一段 PostBack 的事件。
看來就是因為在上面情況中,IE 不會送出 ImageButton 的 x 跟 y 值導致 ImageButton1 的 Click 事件沒有被引發了。
解決方法也不難,可以這樣做:
如果去檢視 ASP.NET render 的 HTML,可以找到:
var theForm = document.forms[‘form1’];
if (!theForm) {
theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
我們可以利用 __doPostBack
來解決,因為它做的事情就是將控制項名稱放入 __EVENTTARGET
的值再送出。
將 submitHandler 事件改為:
submitHandler: function (form) {
alert('做些事..開視窗之類的');
__doPostBack('<%=控制項名稱.ClientID %>', '');
}
或是乾脆直接塞值給 __EVENTTARGET
:
submitHandler: function (form) {
alert('做些事..開視窗之類的');
form.__EVENTTARGET.value = '<%= ImageButton1.ClientID %>';
form.submit();
}
以上分享。
如果有更不錯的解法,或是觀念不大正確的地方,請不吝給予指導,感謝 : )