对具有多个输入的 .form-group 进行 jQuery 验证
使用
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>
问题是,例如,一旦您选择一个状态,输入就会变为有效,并且其
.form-group
父级
会失去
.has-error
类
,即使
兄弟输入
(即 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
类(因为样式)。
编辑 2
Jsfiddle 来演示该问题。
这是我最终得到的解决方案。它比我想象的要简单。正如人们之前指出的那样,任何
form-group
一次都应只包含一个
form-control
。因此,最简单的解决方案是将第二个
form-group
放入第一个
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 。
您正在调用一个函数,而该函数又调用另一个函数,依此类推,直到达到调用堆栈限制。我假设问题出在您调用
.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
使用插件提供的选项无法实现。有效/无效类在被验证的元素上切换。
highlight
和
unhighlight
函数可以修改为使用 jQuery DOM 遍历等切换其他元素上的类。
但是,当父容器的任何子元素无效时,您需要使父容器“无效”的逻辑……插件没有配备此功能。一旦无效子元素触发父元素上的错误类,任何有效子元素都会将有效类应用于同一父元素。
一种解决方法是使用
外部
keyup
和
change
处理程序,该处理程序查看所有同级输入元素上的类并相应地切换其父类。根据您自己的代码,未经测试...
$('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
... 如此反复。