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 an 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
errorPlacement
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");
};