Is there any way to trigger a specific jquery-unobtrusive rule on one field, when the value in another field changes?
I have a form with two date fields (say start/end) on it, with validation that end
must be greater than start
. This works fine in the simple case of changing end
after start
is already set. What it doesn't do is allow for is:
end
first and then setting start
start
after both have already been set, and violating the constraintServer side validation will catch it of course, but it looks bad to have the error on end
stay set even after you have fixed start
, or no error showing up when the value in end
is changed to an invalid value. The reason to trigger a specific rule is that I don't want to fire off the required
or date
format rules on the same field before the user has had a chance to enter a value. The form starts off 'clean'. However, if that isn't possible then firing all the rules is ok.
Sorry for no code samples, but I don't even know where to start with this.
Update:
What i've done for the moment is to dig around in the model (since this is an asp.net mvc project), find the attribute, and read it's properties directly.
var controllerCtx = ViewContext.Controller.ControllerContext;
var da = ViewData.ModelMetadata.GetValidators(controllerCtx)
.SelectMany(x => x.GetClientValidationRules())
.Where(x => x.ValidationType == "isdateafter")
.FirstOrDefault();
var otherid = da == null ? "" : da.ValidationParameters["propertytested"];
Then in the normal HTML part, I do a test on the start
and see if it is a date picker, then wire up a basic check, and fire off all validation rules. Since there aren't many rules, I just check to see if there is a value in the end
field before running them. I'd like to use the ingenious solution below, and will give it a go when I have a bit of free time this week.
@if (otherid != "") {
<text>
var other = $("#@otherid");
if (other && other.hasClass('hasDatepicker')) { // if the other box is a date/time picker
other.datetimepicker('option', 'onSelect', function(dateText, instance) {
var lowerTime = $(this).datetimepicker('getDate');
$("#@id").datetimepicker('option', 'minDate', new Date(lowerTime.getTime()));
if ($("#@id").val()) { // if there is a value in the other
$('form').data('validator').element('#@id');
}
});
}
</text>
}
Unobtrusive Validation means without writing a lot of validation code, you can perform simple client-side validation by adding the suitable attributes and including the suitable script files. These unobtrusive validation libraries need to be added: jquery.validate.min.js.
Specifying hidden form field validation. To specify hidden field validation, you do the following: Create one HTML input element or CFML cfinput tag of type="hidden" for each validation rule. Specify the name of the field to validate as the first part of the hidden field name.
You can disable the unobtrusive validation from within the razor code via this Html Helper property: HtmlHelper. ClientValidationEnabled = false; That way you can have unobtrusive validation on and off for different forms according to this setting in their particular view/partial view.
Field validation is an automated process of ascertaining that each field contains the correct value before the form is accepted. The concept is straightforward.
This might work for you...
$('form').data('validator').element('#Key')
This grabs the validator off of your form, and forces validation on an individual item.
http://docs.jquery.com/Plugins/Validation/Validator/element#element
UPDATE
See if this continues to help!
$.extend($.validator.prototype, {
elementWithRule: function(element, rule) {
element = this.clean(element);
this.lastElement = element;
this.prepareElement(element);
this.currentElements = $(element);
var result = this.checkSpecificRule(element, rule);
if (result) {
delete this.invalid[element.name];
} else {
this.invalid[element.name] = true;
}
if (!this.numberOfInvalids()) {
// Hide error containers on last error
this.toHide = this.toHide.add(this.containers);
}
this.showErrors();
return result;
},
checkSpecificRule: function(element, rule) {
element = this.clean(element);
// if radio/checkbox, validate first element in group instead
if (this.checkable(element)) {
element = this.findByName(element.name).not(this.settings.ignore)[0];
}
var findRule = { },
checkRule = $(element).rules()[ rule ];
var rules;
if (checkRule) {
findRule[rule] = checkRule;
rules = findRule;
}
if (!rules) {
return;
}
var dependencyMismatch = false;
for (var method in rules) {
var rule = { method: method, parameters: rules[method] };
try {
var result = $.validator.methods[method].call(this, element.value.replace( /\r/g , ""), element, rule.parameters);
// if a method indicates that the field is optional and therefore valid,
// don't mark it as valid when there are no other rules
if (result == "dependency-mismatch") {
dependencyMismatch = true;
continue;
}
dependencyMismatch = false;
if (result == "pending") {
this.toHide = this.toHide.not(this.errorsFor(element));
return;
}
if (!result) {
this.formatAndAdd(element, rule);
return false;
}
} catch(e) {
this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
+ ", check the '" + rule.method + "' method", e);
throw e;
}
}
if (dependencyMismatch)
return;
if (this.objectLength(rules))
this.successList.push(element);
return true;
}
});
// Then use it like this...
$('form').data('validator').elementWithRule('#Key', 'required');
There didn't appear to be any built in way to do this, so I just hacked something together! :)
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