I have a number of spots in my code where I have pairs of related start and end date fields (range). I need to validate that the start is before the end date. I'm using the jQuery validation plugin.
Here's my code: http://jsfiddle.net/jinglesthula/dESz2/
Markup:
<form id="myform">
<input type="text" name="startDate" id="startDate" class="validDate" />
<br/>
<input type="text" name="endDate" id="endDate" class="validDate" />
<br/>
<input type="submit" />
</form>
js:
$(function() {
// simple date mm/dd/yyyy format
$.validator.addMethod('validDate', function(value, element) {
return this.optional(element) || /^(0?[1-9]|1[012])[ /](0?[1-9]|[12][0-9]|3[01])[ /][0-9]{4}$/.test(value);
}, 'Please provide a date in the mm/dd/yyyy format');
$.validator.addMethod('dateBefore', function(value, element, params) {
// if end date is valid, validate it as well
var end = $(params);
if (!end.data('validation.running')) {
$(element).data('validation.running', true);
this.element(end);
$(element).data('validation.running', false);
}
return this.optional(element) || this.optional(end[0]) || new Date(value) < new Date(end.val());
}, 'Must be before corresponding end date');
$.validator.addMethod('dateAfter', function(value, element, params) {
// if start date is valid, validate it as well
var start = $(params);
if (!start.data('validation.running')) {
$(element).data('validation.running', true);
this.element(start);
$(element).data('validation.running', false);
}
return this.optional(element) || this.optional(start[0]) || new Date(value) > new Date($(params).val());
}, 'Must be after corresponding start date');
$('#myform').validate({ // initialize the plugin
rules: {
startDate: {dateBefore: '#endDate', required: true},
endDate: {dateAfter: '#startDate', required: true}
},
submitHandler: function (form) { // for demo
alert('valid form submitted'); // for demo
return false; // for demo
}
});
});
I want to make it so that whenever one date field changes that I do a check to make sure the range is valid (e.g. start < end).
What I'm running into is that if I enter a valid range, then change the year of the end date to be the year prior to the year of the start date it will clear the error on the start date, but not clear the error on the end date field. I've debugged and stepped into the dateAfter method and seen it return true! I can even (without further modification of the field values) hit the submit button and then the error clears and the form submits.
Any idea why it's not clearing it?
edit To further clarify the steps I'm taking to reproduce:
Ah, figured it out (or at least solved the issue). The validation plugin was likely not designed to allow for validation of a second field within the running of a given field's method(s). Probably there's an internal reference to the field currently being validated, so you need to do the validations in serial rather than overlapping them.
I've added an update to the fiddle here where you can see that using setTimeout to ensure that the 'other field' validates after the first indeed clears up the problem: http://jsfiddle.net/jinglesthula/dESz2/3/
this.element(end);
becomes
setTimeout($.proxy(
function () {
this.element(end);
}, this), 0);
I also added a setTimeout for the clearing of the 'validation.running' flag to ensure it doesn't get cleared until after the 'other' field validates.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With