JQuery Validator Checkbox onClick 更新错误消息不一致的行为?
JQuery Validator Checkbox onClick update error message inconsistent behavior?
我创建了一个非常标准的复选框 JQuery 验证示例:https://jsfiddle.net/rbL62zm8/1/
为清楚起见,console.log
语句已从该问题的代码中省略。
验证 rules
需要选择数字或字符串类型。如果选择数字,则还必须选择数字类型(Int、Float 或 Double)。
var validationRules = {
debug: true,
rules: {
'type': {
// Number or String
required: true,
},
'numeric': {
// Int, Float or Double.
required: '#typeNumber:checked'
}
},
messages: {
'type': {
required: 'A data type is required.'
},
'numeric': {
required: 'A numeric data type is required.'
}
},
onclick: function(element) {
$(element).valid();
},
submitHandler: function(form) {
$("#validationMsg").html("The form is valid.");
return false;
},
errorPlacement: function(label, element) {
$("#validationMsg").html(label);
},
}
对应的HTML形式:
<form id="mainForm" name="mainForm" method='post' action=''>
<input type="checkbox" name="type" class="type-group" id="typeNumber" value="Number">
<label for="typeNumber">Number</label>
<input type="checkbox" name="type" class="type-group" id="typeString" value="String" checked>
<label for="typeString">String</label>
<br />
<input type="checkbox" name="numeric" class="numeric-group" id="numericInt" value="Int">
<label for="numericInt">Int</label>
<input type="checkbox" name="numeric" class="numeric-group" id="numericFloat" value="Float">
<label for="numericFloat">Float</label>
<input type="checkbox" name="numeric" class="numeric-group" id="numericDouble" value="Double">
<label for="numericDouble">Double</label>
<br />
<input type='submit' name='Submit' value='Submit' />
<input type='reset' name='Reset' value='Reset' />
</form>
<div id="validationMsg"></div>
表单的默认状态确保勾选字符串复选框:
我添加了一个 onclick
实现,试图在复选框被选中或未选中时验证表单。
用例 #1
- 运行 JSFiddle。
- 取消选中字符串复选框。
结果:显示错误信息,正确。
用例 #2
- 运行 JSFiddle。
- 取消选中字符串复选框。
- 勾选字符串复选框。
结果:错误消息显示并保持可见。这似乎不一致,因为显示错误消息的操作(取消勾选复选框)被反转,但错误消息未更新。
问题:
如何在 所有 复选框的状态发生变化时验证它们?
更新
我通过添加
在 validation configuration object 中实现了 invalidHandler
invalidHandler: function(form, validator) {
var errors = validator.numberOfInvalids();
console.log('Number of invalids: %s', errors);
},
JSFiddle:https://jsfiddle.net/xz1a43fm/
invalidHandler
函数仅在表单处于无效状态时调用。因此,勾选字符串复选框会使表单进入有效状态,并且不会调用 invalidHandler
。
submitHandler
是我能找到的与 invalidHandler
对应的最接近的东西 - 但是它只被称为 onSubmit
而不是 onClick
.
最终解决方案
我有三个要求:
- 实时验证:在用户与表单交互时验证复选框,而不仅仅是在提交时。
- 双向依赖:验证双向依赖。 IE。如果勾选
Number
,则必须勾选 Float
、Int
或 Double
,而且如果 Float
、Int
或 Double
已打勾,Number
必须打勾。
- 不要 Hack:不要在大型自定义验证方法中重写内置规则。
实时验证:实现自定义 onclick
函数很常见,但我遗漏了两个关键细节:
- 验证整个表单,而不是单个元素。通过在整个表单上调用
valid()
,可以评估复选框组之间的所有相互依赖性。
- 检查有效状态并在需要时手动清除错误消息(如@ZirboFilip 所建议)。
最终的 onclick
处理程序:
onclick: function(element) {
// Validate the entire form.
var valid = $('#mainForm').valid();
// Clear error message manually if appropriate.
if (valid) {
$("#validationMsg").html('');
}
}
双向依赖:
required 属性非常适合单向依赖,但不适用于复选框组依赖。一个合理的规则可能是:
'type': {
required: true,
},
'numeric': {
required: '#typeNumber:checked',
}
然而,这仅说明如果选中任何类型(数字或字符串),则需要数字类型。因此以下是有效的:
...这不是我想要的。我添加了自定义验证方法:
jQuery.validator.addMethod("checkDependencies", function(value, element) {
// return true if field is ok or should be ignored.
var intChecked = $('#numericInt').prop('checked');
var floatChecked = $('#numericFloat').prop('checked');
var doubleChecked = $('#numericDouble').prop('checked');
var numberChecked = $('#typeNumber').prop('checked');
var stringChecked = $('#typeString').prop('checked');
var numericTypeChecked = intChecked || floatChecked || doubleChecked;
if (!numberChecked && stringChecked) {
return !numericTypeChecked;
}
// Fall-back on built in rules for everything else.
return true;
});
我将在下面更详细地讨论这个问题,同时满足我的第三个要求。
Don't Hack: 我只有一个额外的要求没有被内置规则和依赖项所涵盖,即当一个 Int 时,String 不是一个有效的类型,选择浮点数或双精度数。我在自定义规则(上面的代码)中对此进行了编码。相关代码重复如下:
if (!numberChecked && stringChecked) {
return !numericTypeChecked;
}
// Fall-back on built in rules for everything else.
return true;
然而,经过这次检查,我returntrue
。虽然很想在同一规则中编写其他组合,但通过 returning true
,我继续使用 required
规则,即:
'numeric': {
required: '#typeNumber:checked',
}
最终 JSFiddler:https://jsfiddle.net/bmg2dcha/1/
添加这个:
if($(element).valid()){
("#validationMsg").html("");
}
在 onclick: function(element) { ... }
里面应该没问题。
我创建了一个非常标准的复选框 JQuery 验证示例:https://jsfiddle.net/rbL62zm8/1/
为清楚起见,console.log
语句已从该问题的代码中省略。
验证 rules
需要选择数字或字符串类型。如果选择数字,则还必须选择数字类型(Int、Float 或 Double)。
var validationRules = {
debug: true,
rules: {
'type': {
// Number or String
required: true,
},
'numeric': {
// Int, Float or Double.
required: '#typeNumber:checked'
}
},
messages: {
'type': {
required: 'A data type is required.'
},
'numeric': {
required: 'A numeric data type is required.'
}
},
onclick: function(element) {
$(element).valid();
},
submitHandler: function(form) {
$("#validationMsg").html("The form is valid.");
return false;
},
errorPlacement: function(label, element) {
$("#validationMsg").html(label);
},
}
对应的HTML形式:
<form id="mainForm" name="mainForm" method='post' action=''>
<input type="checkbox" name="type" class="type-group" id="typeNumber" value="Number">
<label for="typeNumber">Number</label>
<input type="checkbox" name="type" class="type-group" id="typeString" value="String" checked>
<label for="typeString">String</label>
<br />
<input type="checkbox" name="numeric" class="numeric-group" id="numericInt" value="Int">
<label for="numericInt">Int</label>
<input type="checkbox" name="numeric" class="numeric-group" id="numericFloat" value="Float">
<label for="numericFloat">Float</label>
<input type="checkbox" name="numeric" class="numeric-group" id="numericDouble" value="Double">
<label for="numericDouble">Double</label>
<br />
<input type='submit' name='Submit' value='Submit' />
<input type='reset' name='Reset' value='Reset' />
</form>
<div id="validationMsg"></div>
表单的默认状态确保勾选字符串复选框:
我添加了一个 onclick
实现,试图在复选框被选中或未选中时验证表单。
用例 #1
- 运行 JSFiddle。
- 取消选中字符串复选框。
结果:显示错误信息,正确。
用例 #2
- 运行 JSFiddle。
- 取消选中字符串复选框。
- 勾选字符串复选框。
结果:错误消息显示并保持可见。这似乎不一致,因为显示错误消息的操作(取消勾选复选框)被反转,但错误消息未更新。
问题: 如何在 所有 复选框的状态发生变化时验证它们?
更新
我通过添加
在 validation configuration object 中实现了invalidHandler
invalidHandler: function(form, validator) {
var errors = validator.numberOfInvalids();
console.log('Number of invalids: %s', errors);
},
JSFiddle:https://jsfiddle.net/xz1a43fm/
invalidHandler
函数仅在表单处于无效状态时调用。因此,勾选字符串复选框会使表单进入有效状态,并且不会调用 invalidHandler
。
submitHandler
是我能找到的与 invalidHandler
对应的最接近的东西 - 但是它只被称为 onSubmit
而不是 onClick
.
最终解决方案
我有三个要求:
- 实时验证:在用户与表单交互时验证复选框,而不仅仅是在提交时。
- 双向依赖:验证双向依赖。 IE。如果勾选
Number
,则必须勾选Float
、Int
或Double
,而且如果Float
、Int
或Double
已打勾,Number
必须打勾。 - 不要 Hack:不要在大型自定义验证方法中重写内置规则。
实时验证:实现自定义 onclick
函数很常见,但我遗漏了两个关键细节:
- 验证整个表单,而不是单个元素。通过在整个表单上调用
valid()
,可以评估复选框组之间的所有相互依赖性。 - 检查有效状态并在需要时手动清除错误消息(如@ZirboFilip 所建议)。
最终的 onclick
处理程序:
onclick: function(element) {
// Validate the entire form.
var valid = $('#mainForm').valid();
// Clear error message manually if appropriate.
if (valid) {
$("#validationMsg").html('');
}
}
双向依赖: required 属性非常适合单向依赖,但不适用于复选框组依赖。一个合理的规则可能是:
'type': {
required: true,
},
'numeric': {
required: '#typeNumber:checked',
}
然而,这仅说明如果选中任何类型(数字或字符串),则需要数字类型。因此以下是有效的:
...这不是我想要的。我添加了自定义验证方法:
jQuery.validator.addMethod("checkDependencies", function(value, element) {
// return true if field is ok or should be ignored.
var intChecked = $('#numericInt').prop('checked');
var floatChecked = $('#numericFloat').prop('checked');
var doubleChecked = $('#numericDouble').prop('checked');
var numberChecked = $('#typeNumber').prop('checked');
var stringChecked = $('#typeString').prop('checked');
var numericTypeChecked = intChecked || floatChecked || doubleChecked;
if (!numberChecked && stringChecked) {
return !numericTypeChecked;
}
// Fall-back on built in rules for everything else.
return true;
});
我将在下面更详细地讨论这个问题,同时满足我的第三个要求。
Don't Hack: 我只有一个额外的要求没有被内置规则和依赖项所涵盖,即当一个 Int 时,String 不是一个有效的类型,选择浮点数或双精度数。我在自定义规则(上面的代码)中对此进行了编码。相关代码重复如下:
if (!numberChecked && stringChecked) {
return !numericTypeChecked;
}
// Fall-back on built in rules for everything else.
return true;
然而,经过这次检查,我returntrue
。虽然很想在同一规则中编写其他组合,但通过 returning true
,我继续使用 required
规则,即:
'numeric': {
required: '#typeNumber:checked',
}
最终 JSFiddler:https://jsfiddle.net/bmg2dcha/1/
添加这个:
if($(element).valid()){
("#validationMsg").html("");
}
在 onclick: function(element) { ... }
里面应该没问题。