jQuery 对具有多个输入的 .form-group 进行验证
jQuery Validation on a .form-group with multiple inputs
使用 jQuery Validation 插件,我为 Bootstrap form
定义了以下内容:
$(".form-with-validation").validate({
errorClass: "help-block",
errorElement: "span",
highlight: function(element) {
$(element).closest('.form-group').addClass('has-error');
},
unhighlight: function(element) {
$(element).closest('.form-group').removeClass('has-error');
}
});
它适用于简单的表单。但是,当 .form-group
包含需要验证的多个输入(内联)时,带有 highlight
和 unhighlight
的部分不起作用:
<div class="form-group">
<label class="col-md-4 control-label">State & Zip</label>
<div class="col-md-3">
<select class="form-control required" name="state">
...
</select>
</div>
<div class="col-md-3">
<input type="text" class="form-control required" name="zip">
</div>
</div>
问题是一旦你select一个状态,输入就变得有效,它的.form-group
父失去.has-error
class ,即使 同级输入(即 zip)仍然无效(即下面有一个 .help-block
跨度):
因此,我将 unhighlight
部分更改为以下内容:
unhighlight: function(element) {
var formGroup = $(element).closest('.form-group');
var formGroupIsValid = true;
formGroup.find('input').each(function(){
if (! $(this).valid())
formGroupIsValid = false;
});
if (formGroupIsValid)
formGroup.removeClass('has-error');
}
但我收到以下错误:
Uncaught RangeError: Maximum call stack size exceeded
知道为什么吗?我尝试了很多方法,但每次都得到相同的错误。
编辑
如果可能(因为样式),我更愿意坚持使用 div.form-group
.has-error
class。
编辑 2
Jsfiddle 演示问题。
您正在调用一个函数,该函数又调用另一个函数,依此类推,直到达到调用堆栈限制。当您调用 .valid()
时,我假设问题出在您的 .each
循环中。
不过,您不必执行任何这些操作。而不是针对 form-group
,您应该专门针对输入周围的内容,这样您就不必更改 unhightlight
函数。例如:
<div class="form-group">
<label class="col-md-4 control-label">State & Zip</label>
<div class="col-md-3 inputToValidate">
<select class="form-control required" name="state">
...
</select>
</div>
<div class="col-md-3 inputToValidate">
<input type="text" class="form-control required" name="zip">
</div>
</div>
然后将 JavaScript 代码更新为:
$(".form-with-validation").validate({
errorClass: "help-block",
errorElement: "span",
highlight: function(element) {
$(element).closest('.inputToValidate').addClass('has-error');
},
unhighlight: function(element) {
$(element).closest('.inputToValidate').removeClass('has-error');
}
});
I'd prefer to stick with div.form-group having .has-error class if possible
插件提供的选项无法实现。 valid/invalid classes 在被验证的元素上切换。可以修改 highlight
和 unhighlight
函数以使用 jQuery DOM 遍历等在其他元素上切换 classes
但是,您需要在其任何子容器无效时创建父容器 "invalid" 的逻辑...该插件不具备此功能。一旦无效的子元素在父元素上触发错误 class,任何有效的子元素都会将有效的 class 应用于同一父元素。
解决方法是 外部 keyup
和 change
处理程序,它查看所有同级输入元素上的 classes 并切换它的父 class 相应地。基于您自己的代码且未经测试...
$('input, select').on('keyup change', function() {
var formGroup = $(this).closest('.form-group');
var formGroupIsValid = true;
formGroup.find('input, select').each(function(){
if (! $(this).valid()) {
formGroupIsValid = false;
}
});
if (formGroupIsValid) {
formGroup.removeClass('has-error');
} else {
formGroup.addClass('has-error');
}
});
I get the following error: Uncaught RangeError: Maximum call stack size exceeded
.... Any ideas why?
是的,您正在从 .validate()
方法中调用 .valid()
方法(通过 unhighlight
)。所以从这个方法中调用 $(this).valid()
只会导致 unhighlight
被再次调用......等等无限期。
您不必使用 form-with-validation class 您可以通过选择 inputToValidate class 来定位您想要验证的所有表单域。它也简单得多。你也可能想使用 toggleClass.
$(".inputToValidaten").validate({
errorClass: "help-block",
errorElement: "span",
highlight: function(element) {
$(this).toggleClass('has-error');
},
unhighlight: function(element) {
$(this).toggleClass('has-error');
}
});
更新和编辑
好的。所以这里的代码可以在任何带有表单控件 class 的嵌套表单字段上工作。它将上升并使用表单组 class 获取最接近的元素,然后将验证代码添加到其中。
$(".form-control").validate({
errorClass: "help-block",
errorElement: "span",
highlight: function(e) {
$(e.target).closest('.form-group').toggleClass('has-error');
},
unhighlight: function(e) {
$(e.target).closest('.form-group').toggleClass('has-error');
}
});
这是我最终得到的解决方案。这比我想象的要简单。正如人们之前指出的那样,任何 form-group
应该一次只包含一个 form-control
。因此,最简单的解决方案是将第二个 form-group
放在第一个里面,然后将第二个 form-control
放在那里:
<div class="form-group">
<label class="col-md-4 control-label">State & Zip</label>
<div class="col-md-6">
<div class="row">
<div class="col-sm-6">
<select class="form-control required" name="state">
...
</select>
</div>
<div class="col-sm-6 form-group" style="margin-bottom:0;padding-right:0">
<input type="text" class="form-control required" name="zip">
</div>
</div>
</div>
</div>
仅需几个 CSS 样式,它就可以完美运行并且看起来不错。这是 jsfiddle.
使用 jQuery Validation 插件,我为 Bootstrap form
定义了以下内容:
$(".form-with-validation").validate({
errorClass: "help-block",
errorElement: "span",
highlight: function(element) {
$(element).closest('.form-group').addClass('has-error');
},
unhighlight: function(element) {
$(element).closest('.form-group').removeClass('has-error');
}
});
它适用于简单的表单。但是,当 .form-group
包含需要验证的多个输入(内联)时,带有 highlight
和 unhighlight
的部分不起作用:
<div class="form-group">
<label class="col-md-4 control-label">State & Zip</label>
<div class="col-md-3">
<select class="form-control required" name="state">
...
</select>
</div>
<div class="col-md-3">
<input type="text" class="form-control required" name="zip">
</div>
</div>
问题是一旦你select一个状态,输入就变得有效,它的.form-group
父失去.has-error
class ,即使 同级输入(即 zip)仍然无效(即下面有一个 .help-block
跨度):
因此,我将 unhighlight
部分更改为以下内容:
unhighlight: function(element) {
var formGroup = $(element).closest('.form-group');
var formGroupIsValid = true;
formGroup.find('input').each(function(){
if (! $(this).valid())
formGroupIsValid = false;
});
if (formGroupIsValid)
formGroup.removeClass('has-error');
}
但我收到以下错误:
Uncaught RangeError: Maximum call stack size exceeded
知道为什么吗?我尝试了很多方法,但每次都得到相同的错误。
编辑
如果可能(因为样式),我更愿意坚持使用 div.form-group
.has-error
class。
编辑 2
Jsfiddle 演示问题。
您正在调用一个函数,该函数又调用另一个函数,依此类推,直到达到调用堆栈限制。当您调用 .valid()
时,我假设问题出在您的 .each
循环中。
不过,您不必执行任何这些操作。而不是针对 form-group
,您应该专门针对输入周围的内容,这样您就不必更改 unhightlight
函数。例如:
<div class="form-group">
<label class="col-md-4 control-label">State & Zip</label>
<div class="col-md-3 inputToValidate">
<select class="form-control required" name="state">
...
</select>
</div>
<div class="col-md-3 inputToValidate">
<input type="text" class="form-control required" name="zip">
</div>
</div>
然后将 JavaScript 代码更新为:
$(".form-with-validation").validate({
errorClass: "help-block",
errorElement: "span",
highlight: function(element) {
$(element).closest('.inputToValidate').addClass('has-error');
},
unhighlight: function(element) {
$(element).closest('.inputToValidate').removeClass('has-error');
}
});
I'd prefer to stick with div.form-group having .has-error class if possible
插件提供的选项无法实现。 valid/invalid classes 在被验证的元素上切换。可以修改 highlight
和 unhighlight
函数以使用 jQuery DOM 遍历等在其他元素上切换 classes
但是,您需要在其任何子容器无效时创建父容器 "invalid" 的逻辑...该插件不具备此功能。一旦无效的子元素在父元素上触发错误 class,任何有效的子元素都会将有效的 class 应用于同一父元素。
解决方法是 外部 keyup
和 change
处理程序,它查看所有同级输入元素上的 classes 并切换它的父 class 相应地。基于您自己的代码且未经测试...
$('input, select').on('keyup change', function() {
var formGroup = $(this).closest('.form-group');
var formGroupIsValid = true;
formGroup.find('input, select').each(function(){
if (! $(this).valid()) {
formGroupIsValid = false;
}
});
if (formGroupIsValid) {
formGroup.removeClass('has-error');
} else {
formGroup.addClass('has-error');
}
});
I get the following error:
Uncaught RangeError: Maximum call stack size exceeded
.... Any ideas why?
是的,您正在从 .validate()
方法中调用 .valid()
方法(通过 unhighlight
)。所以从这个方法中调用 $(this).valid()
只会导致 unhighlight
被再次调用......等等无限期。
您不必使用 form-with-validation class 您可以通过选择 inputToValidate class 来定位您想要验证的所有表单域。它也简单得多。你也可能想使用 toggleClass.
$(".inputToValidaten").validate({
errorClass: "help-block",
errorElement: "span",
highlight: function(element) {
$(this).toggleClass('has-error');
},
unhighlight: function(element) {
$(this).toggleClass('has-error');
}
});
更新和编辑
好的。所以这里的代码可以在任何带有表单控件 class 的嵌套表单字段上工作。它将上升并使用表单组 class 获取最接近的元素,然后将验证代码添加到其中。
$(".form-control").validate({
errorClass: "help-block",
errorElement: "span",
highlight: function(e) {
$(e.target).closest('.form-group').toggleClass('has-error');
},
unhighlight: function(e) {
$(e.target).closest('.form-group').toggleClass('has-error');
}
});
这是我最终得到的解决方案。这比我想象的要简单。正如人们之前指出的那样,任何 form-group
应该一次只包含一个 form-control
。因此,最简单的解决方案是将第二个 form-group
放在第一个里面,然后将第二个 form-control
放在那里:
<div class="form-group">
<label class="col-md-4 control-label">State & Zip</label>
<div class="col-md-6">
<div class="row">
<div class="col-sm-6">
<select class="form-control required" name="state">
...
</select>
</div>
<div class="col-sm-6 form-group" style="margin-bottom:0;padding-right:0">
<input type="text" class="form-control required" name="zip">
</div>
</div>
</div>
</div>
仅需几个 CSS 样式,它就可以完美运行并且看起来不错。这是 jsfiddle.