【发布时间】:2017-02-01 21:32:49
【问题描述】:
我正在使用 Jörn Zaefferer 的 jQuery 验证插件以及 jQuery UI 日期选择器。我创建了一组自定义规则来验证开始日期是否早于结束日期。
我遇到的问题是,当我的范围无效并使用 datepicker UI 更改日期以使范围有效时,我看到验证在为日期选择器触发 onSelect 回调。
我希望日期选择器会在用户选择时更新输入的值,并且任何验证代码都会在发生这种情况时运行并查看新值。但这似乎没有发生。
我尝试在初始化验证之前初始化日期选择器,希望事件的连接顺序会有所不同,但您可以看到它没有帮助。
要重现问题,请在开头输入给定月份的 15 号,最后输入同一个月的 7 号。单击开始字段,然后单击或跳出以触发验证。字段正确无效。现在单击开始字段并选择同月的第一天。注意此时控制台上的输出。
代码,供参考:
HTML
<form id="daterange-form">
<div class="form-group">
<label for="startDate">Start Date</label>
<input type="text" id="startDate" name="startDate" class="validDate form-control" />
</div>
<div class="form-group">
<label for="endDate">End Date</label>
<input type="text" id="endDate" name="endDate" class="validDate form-control" />
</div>
<button type="submit" class="btn">Submit</button>
</form>
JavaScript
// Custom Rules
$.validator.addMethod('dateBefore', function(value, element, params) {
// if end date is valid, validate it as well
console.log('dateBefore', value, element, params)
var end = $(params);
if (!end.data('validation.running')) {
$(element).data('validation.running', true);
// The validator internally keeps track of which element is being validated currently. This ensures that validating 'end' will not trample 'start'
// see http://stackoverflow.com/questions/22107742/jquery-validation-date-range-issue
setTimeout($.proxy(
function() {
this.element(end);
}, this), 0);
// Ensure clearing the 'flag' happens after the validation of 'end' to prevent endless looping
setTimeout(function(){
$(element).data('validation.running', false);
}, 0);
}
return this.optional(element) || this.optional(end[0]) || new Date(value) < new Date(end.val());
}, 'Must be before its end date');
$.validator.addMethod('dateAfter', function(value, element, params) {
// if start date is valid, validate it as well
console.log('dateAfter', value, element, params)
var start = $(params);
if (!start.data('validation.running')) {
$(element).data('validation.running', true);
// The validator internally keeps track of which element is being validated currently. This ensures that validating 'end' will not trample 'start'
// see http://stackoverflow.com/questions/22107742/jquery-validation-date-range-issue
setTimeout($.proxy(
function() {
this.element(start);
}, this), 0);
// Ensure clearing the 'flag' happens after the validation of 'end' to prevent endless looping
setTimeout(function() {
$(element).data('validation.running', false);
}, 0);
}
return this.optional(element) || this.optional(start[0]) || new Date(value) > new Date($(params).val());
}, 'Must be after its start date');
// Code setting up datepicker and validation
$('#startDate, #endDate').datepicker({
onSelect: function(dateText, inst) {
console.log('onSelect', dateText, inst)
}
});
$('#daterange-form').validate({
debug: true,
rules: {
startDate: {dateBefore: '#endDate'},
endDate: {dateAfter: '#startDate'}
}
});
旁注:规则中的超时和代理调用是因为此版本的库在内部假定串行验证。如果您尝试在规则中间验证另一个字段,就会发生坏事。 validation.running 信号量代码是为了防止无限循环。
【问题讨论】:
-
我应该注意到,在我们的代码中,我们目前正在使用这种先聚焦后模糊的解决方法stackoverflow.com/a/19838943/749227。大多数情况下,我很好奇为什么日期选择器似乎会导致在实际更新值之前触发验证正在寻找的任何事件,以及如何绕过它而不必记住每次我们都有复制粘贴相同的解决方法一个经过验证的日期范围。
标签: javascript jquery jquery-ui datepicker jquery-validate