What is the proper way to override the ErrorPlacement function in jquery.validate.unobtrusive?
Looking at the jquery.validate.unobtrusive.js script it appears that the developers intention would allow you to apply your own ErrorPlacement function by setting $jQval.unobtrusive.options.
In the validationInfo(form) function that defines the errorPlacement function we see a call to execInContext("errorPlacement", arguments).
It would seem that if we create a errorPlacement function under $.validator.unobtrusive.options then this will be called.
$.validator.unobtrusive.options = {
errorPlacement: function () {
console.log("hello");
}
};
The issue is that this must configured after jquery.validate.js and before jquery.validate.unobtrusive.js is referenced. Otherwise $jQval.unobtrusive.options is null and $form.data(data_validation, result) will not be set again.
function validationInfo(form) {
var $form = $(form),
result = $form.data(data_validation),
onResetProxy = $.proxy(onReset, form),
defaultOptions = $jQval.unobtrusive.options || {},
execInContext = function (name, args) {
var func = defaultOptions[name];
func && $.isFunction(func) && func.apply(form, args);
}
if (!result) {
result = {
options: { // options structure passed to jQuery Validate's validate() method
errorClass: defaultOptions.errorClass || "input-validation-error",
errorElement: defaultOptions.errorElement || "span",
errorPlacement: function () {
onError.apply(form, arguments);
execInContext("errorPlacement", arguments);
},
invalidHandler: function () {
onErrors.apply(form, arguments);
execInContext("invalidHandler", arguments);
},
messages: {},
rules: {},
success: function () {
onSuccess.apply(form, arguments);
execInContext("success", arguments);
}
},
attachValidation: function () {
$form
.off("reset." + data_validation, onResetProxy)
.on("reset." + data_validation, onResetProxy)
.validate(this.options);
},
validate: function () { // a validation function that is called by unobtrusive Ajax
$form.validate();
return $form.valid();
}
};
$form.data(data_validation, result);
}
return result;
}
The other way to get deal with this is to
set the $.validator.unobtrusive.options error Placement Function
remove the Unobtrusive Validation
re apply the unobtrusive validation
$.validator.unobtrusive.options = {
errorPlacement: function () {
console.log("errorPlacement");
}
};
$("#form_selector").removeData("unobtrusiveValidation");
// reapply the form's validator
$.validator.unobtrusive.parse(document);
Or the other option would be to override the function call.
var validator = $("#form_selector").data('validator');
var originalFunction = validator.settings.errorPlacement;
validator.settings.errorPlacement = function(error,element) {
console.log("errorPlacement");
originalFunction(error, element);
};
Which is the proper way of implementing your own errorPlacement method?
3 years late to answer, but turns out I needed exactly this today. It's possible the unobtrusive code has been fixed in that timeframe, but your example code worked just fine for me. I added this to one of my site scripts that was loaded after both jquery.validate.js and jquery.validate.unobtrusive.js:
$.validator.unobtrusive.options = {
errorPlacement: function () {
console.log("hello");
}
};
It worked fine, but with one additional catch: this line has to be ran before document ready. The validationInfo
method is called on document ready via this, from the bottom of jquery.validate.unobtrusive.js
:
$(function () {
$jQval.unobtrusive.parse(document);
});
parse
ultimately calls validationInfo
. The problem with the unobtrusive code is when validationInfo
sets defaultOptions = $jQval.unobtrusive.options || {}
. Clearly if you haven't defined the unobtrusive.options by this point, it'll stupidly set defaultOptions
to a blank object and never check it again, regardless of what you do to $jQval.unobtrusive.options. If they just removed the || {}
everything would work great, since it's just an object reference. Alas...
If you can't set the errorPlacement callback before your document is loaded, or you need to alter it dynamically, just add this one line in one of your scripts that loads after jquery.validate.js
and jquery.validate.unobtrusive.js
:
$.validator.unobtrusive.options = {};
That will cause defaultOptions
to point to an object you can reference. Then, wherever you need, alter $.validator.unobtrusive.options
as you'd expect. Just be careful not to overwrite the object since you wouldn't affect the object pointed to by defaultOptions
if you did. ie, do this:
$.validator.unobtrusive.options.errorPlacement: function () {
console.log("hello");
};
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