本文详细解析jQuery Validate与jQuery Form插件结合使用的三种表单验证与提交方案。通过submitHandler回调、beforeSubmit前置检查以及直接调用valid()方法,分别实现不同控制粒度的验证流程。文章包含完整代码示例,并针对DOCTYPE声明引发的样式兼容性问题提供调试思路与版本建议。
jQuery Validate与Form插件表单验证提交的三种实现方案
概述:本文主要探讨如何利用jquery.validate插件配合jquery.form插件,实现高效的表单验证与提交功能。
方案一:submitHandler回调提交
第一种方案:利用jquery.validate插件提供的submitHandler选项。该选项允许在表单通过所有验证规则后执行特定的回调函数。在此回调函数内部,调用jquery.form插件的方法来执行实际的表单提交操作。
方案二:beforeSubmit前置检查
第二种方案:利用jquery.form插件的beforeSubmit选项。这是一个在表单提交前触发的回调函数,若该函数返回true,则继续提交;若返回false,则终止提交。结合jquery.validate插件的valid()方法,可以在提交前对表单进行实时验证。
方案三:valid方法直接控制
第三种方案:直接调用jquery.validate插件的validate方法。这种方式的优势在于对表单验证流程拥有更高的控制自由度,适合需要复杂逻辑判断的场景。
实例演示:下文将通过三个具体的代码实例,分别阐述上述三种实现方式的具体用法。
第一步:引入CSS样式文件
HTML代码片段如下:
<link rel="stylesheet" type="text/css" media="screen" href="style.css" />
CSS样式文件的具体内容定义如下
input{
height:25px;
line-height:25px;
padding-left:4px;
}
span.checked{
padding: 0px 5px 0px 25px;
margin-left: 10px;
margin-top: 0px;
margin-bottom: 3px;
height: 25px;
line-height:25px;
font-size: 12px;
white-space: nowrap;
text-align: left;
color: #E6594E;
background: url("images/acion2.png") no-repeat 3px; /* #FCEAE8 */
}
span.unchecked{
padding: 0px 5px 0px 25px;
margin-left: 10px;
margin-top: 0px;
margin-bottom: 3px;
height: 23px;
line-height:23px;
font-size: 12px;
border: 1px solid #E6594E;
white-space: nowrap;
text-align: left;
color: #E6594E;
background: #FCEAE8 url("images/acion.png") no-repeat 3px;
}
第二步:载入必要的JavaScript文件
<script language="JavaScript" type="text/JavaScript" src="js/jQuery1.6.2.js"></script>
<script language="JavaScript" type="text/JavaScript" src="js/jquery.form.js"></script>
<script language="JavaScript" type="text/JavaScript" src="js/jquery.validate.js"></script>
<script language="JavaScript" type="text/JavaScript" src="js/localization/messages_tw.js"></script>
HTML页面主体结构内容
<body><span id="result"></span>
<form id='commentForm'>
<fieldset>
<legend>jquery.validate+jquery.form提交的三种方式</legend>
<p>
<label for='cusername'>姓名</label><em>*</em>
<input id='cusername' name='username' size='25' />
</p>
<p>
<label for='cemail'>电子邮件</label><em>*</em>
<input id='cemail' name='email' size='25' />
</p>
<p>
<input class='submit' type='submit' value='提交'>
</p>
</fieldset>
</form>
</body>
第一种提交方式(submitHandler)的JavaScript实现代码
<script language="javascript">
function showResponse(responseText,statusText) {
if(statusText=='success'){
$("#result").html(responseText);
}
}
$(document).ready(function(){
$('#commentForm').validate({
focusCleanup:true,focusInvalid:false,
errorClass: "unchecked",
validClass: "checked",
errorElement: "span",
submitHandler:function(form){
$(form).ajaxSubmit({
type:"post",
url:"test_save.php?time="+ (new Date()).getTime(),
//beforeSubmit: showRequest,
success: showResponse
});
},
errorPlacement:function(error,element){
var s=element.parent().find("span[htmlFor='" + element.attr("id") + "']");
if(s!=null){
s.remove();
}
error.appendTo(element.parent());
},
success: function(label) {
//label.addClass("valid").text("Ok!")
label.removeClass("unchecked").addClass("checked");
},
rules:{
username:{required:true,minlength:3},
email:{
required:true
}
}
});
});
</script>
第二种提交方式(beforeSubmit)的JavaScript实现代码
<script language="javascript">
function showResponse(responseText,statusText) {
if(statusText=='success'){
$("#result").html(responseText);
}
}
function showRequest(formData,jqForm,options){
return $("#commentForm").valid();
}
$(document).ready(function(){
$('#commentForm').submit(function(){
$(this).ajaxSubmit({
type:"post",
url:"test_save.php?time="+ (new Date()).getTime(),
beforeSubmit:showRequest,
success:showResponse
});
return false; //此处必须返回false,阻止常规的form提交
});
$('#commentForm').validate({
focusCleanup:true,focusInvalid:false,
errorClass: "unchecked",
validClass: "checked",
errorElement: "span",
errorPlacement:function(error,element){
var s=element.parent().find("span[htmlFor='" + element.attr("id") + "']");
if(s!=null){
s.remove();
}
error.appendTo(element.parent());
},
success: function(label) {
//label.addClass("valid").text("Ok!")
label.removeClass("unchecked").addClass("checked");
},
rules:{
username:{required:true,minlength:3},
email:{
required:true
}
}
});
});
</script>
第三种提交方式(valid方法)的JavaScript实现代码
<script language="javascript">
var options={
focusCleanup:true,focusInvalid:false,
errorClass: "unchecked",
validClass: "checked",
errorElement: "span",
errorPlacement:function(error,element){
var s=element.parent().find("span[htmlFor='" + element.attr("id") + "']");
if(s!=null){
s.remove();
}
error.appendTo(element.parent());
},
success: function(label) {
//label.addClass("valid").text("Ok!")
label.removeClass("unchecked").addClass("checked");
},
rules:{
username:{required:true,minlength:3},
email:{
required:true
}
}
};
function showResponse(responseText,statusText) {
if(statusText=='success'){
$("#result").html(responseText);
}
}
function showRequest(formData,jqForm,options){
return $("#commentForm").valid();
}
$(document).ready(function(){
validator=$('#commentForm').validate(options);
$("#reset").click(function(){
validator.resetForm();
});
$("button").click(function(){
validator.form();
});
$('#commentForm').submit(function(){
$(this).ajaxSubmit({
type:"post",
url:"test_save.php?time="+ (new Date()).getTime(),
beforeSubmit:showRequest,
success:showResponse
});
return false; //此处必须返回false,阻止常规的form提交
});
});
</script>
DEMO源码:可下载获取完整示例
常见问题与排查
常见问题与排查
1、在编写本文时发现了一个问题:当HTML文件头使用<!DOCTYPE html>声明时,输入框及错误提示信息的样式显示异常。起初以为问题较简单,但深入测试发现:针对“姓名”输入框,验证规则要求至少三个字符。当输入第一、二个字符时,错误提示显示正常;输入第三个字符时,错误提示消失并显示验证通过的“逗号”图标。此时一切看似正常,但若继续输入第四个、第五个字符,则会出现如图所示的异常现象:

如果不使用<!DOCTYPE html>,而是直接使用<html>标签,则不会出现此类问题,显示完全正常。然而,作为前端开发规范,添加<!DOCTYPE html>是必须的。因此,核心问题在于:为何添加<!DOCTYPE html>会导致此类样式异常?
该问题的处理过程较为曲折,此处罗列排查步骤,并在最后给出解决方案。
首先,通过查看错误提示信息,重点关注插入错误信息的代码逻辑。在errorPlacement回调函数中增加了一句:alert(element.parent().html());
errorPlacement:function(error,element){
alert(element.parent().html());
var s=element.parent().find("span[htmlFor='" + element.attr("id") + "']");
if(s!=null){
s.remove();
}
error.appendTo(element.parent());
},
输入第一个字符时,控制台输出如下图所示

输入三个字符并通过验证后,输出如下图所示:

继续输入更多字符后,输出如下图所示

以上现象说明了以下几个关键点:
1、无论验证失败还是成功,errorPlacement:function(...)回调函数都会被调用。
2、s.remove()方法似乎未起到预期的移除作用。
由于编写本文时使用的是<html>而非<!DOCTYPE html>,弹出的内容中显示的是htmlFor="cusername",而不是for="cusername",具体如下图所示:

因此,上述代码中采用了如下处理方式
var s=element.parent().find("span[htmlFor='" + element.attr("id") + "']");
if(s!=null){
s.remove();
}
然而在<!DOCTYPE html>环境下,无法通过htmlFor属性找到<span generated="true" htmlFor="cusername"></span>元素。因此,这里应该将htmlFor改为for属性,即
errorPlacement:function(error,element){
alert(element.parent().html());
var s=element.parent().find("span[for='" + element.attr("id") + "']");
if(s!=null){
s.remove();
}
error.appendTo(element.parent());
},
问题看似已解决。但前文提到,无论验证成功或失败,都会调用errorPlacement:function(...)。因此,可以在该函数中判断是否存在错误,若有错误则显示,从而防止在验证成功后仍重复调用。这样就不必再寻找span的for属性值是否等于当前控件的name名称(例如for="cusername")。改进后的代码如下:
errorPlacement:function(error,element){
if(error.html()!=''){
error.appendTo(element.parent());
}
},
虽然解决了上述问题,但在Chrome和Firefox浏览器中仍存在兼容性问题。若使用Firefox或Chrome测试,会发现焦点离开输入框后无法触发验证,只有点击“提交”按钮后才能验证。该问题的根本原因尚未深入探究,但有一个可行的解决方案:将当前的jquery1.6.2版本替换为jquery1.3.2或jquery1.4(其他低于jquery1.6.2的版本未测试,推测均可解决此问题)。
版本建议与扩展功能
建议:
1、建议使用jquery1.3.2版本,这样可以节省大量时间来解决兼容性问题。
扩展功能:
本示例中的jquery.validate插件解决了remote远程验证只能返回true或false的局限性。现在可以返回代码及具体的错误提示信息,从而满足更人性化的需求。使用方法介绍如下
增加以下函数处理远程验证
function GetRemoteInfo(postUrl,data){
var remote = {
type: "POST",
async: false,
url: postUrl,
dataType: "xml",
data: data,
dataFilter: function(dataXML) {
var result = new Object();
result.Result = jQuery(dataXML).find("Result").text();
result.Msg = jQuery(dataXML).find("Msg").text();
//alert(result.Result);
if (result.Result == "-1") {
result.Result = false;
return result;
}else{
result.Result = result.Result == "1" ? true : false;
return result;
}
}
};
return remote;
}
$(document).ready(function(){
var dataInfo ={email:function(){return $("#cemail").val();}};
var remoteInfo = GetRemoteInfo('check-email.php?time='+(new Date()).getTime(),dataInfo);
$('#commentForm').validate({
rules:{
username:{
required:true,
minlength:3
},
email:{
required:true,
remote:remoteInfo
}
}
});
....
});
check-email.php返回的内容为XML格式,结构如下
<?php
header("Content-Type:text/xml");
echo '<?'.'xml version="1.0" encoding="utf-8"'.' ?>';
?>
<AjaxClass>
<Msg>用户名格式不正确,用户名必须包含testa,请重新输入!</Msg>
<Result>0</Result>
</AjaxClass>
result值为0时,返回false,表示验证失败;result值为1时,返回true,表示验证成功