The following findings may be of interest to understand the difference between :
submitHandler : Called when the form is validated successfully - right before the server postback
invalidHandler : Called if validation fails and there is no post back
@DGreen's solution definitely seems to be the best way to inject special handling if the form validation fails and you need to do something such as display a pop-up validation summary (invalidHandler)
$("form").bind("invalid-form.validate", function () {
alert('invalid!');
});
@PeteHaus solution is the best way to do something if you want to prevent postback of a successfully validated form (submitHandler)
$("form").data("validator").settings.submitHandler = function (form) {
alert('submit'); form.submit(); };
However I was slightly concerned about what behavior I was overriding (or not overriding) by binding to the .validate
method like this - and why I had to do each way differently. So I checked the source. I strongly recommend anybody who wants to understand this procedure more does so too - put in some 'alert' statements or 'debugger' statements and it's pretty easy to follow along*
Anyway it turns out that when the jquery.validate.unobtrusive
handler initializes jquery.validate
plugin it does so in the parseElement()
method by retrieving options created by the validationInfo()
method.
ValidationInfo()
returns the options like this:
options: { // options structure passed to jQuery Validate's validate() method
errorClass: "input-validation-error",
errorElement: "span",
errorPlacement: $.proxy(onError, form),
invalidHandler: $.proxy(onErrors, form),
messages: {},
rules: {},
success: $.proxy(onSuccess, form)
},
The onErrors()
method in jquery.validate.unobtrusive
is responsible for dynamically creating the validation summary panel for MVC. If you're not creating a validation summary panel (with @Html.ValidationSummary()
which must incidentally be contained within the FORM body) then this method is completely inert and does nothing so you don't need to worry.
function onErrors(event, validator) { // 'this' is the form elementz
var container = $(this).find("[data-valmsg-summary=true]"),
list = container.find("ul");
if (list && list.length && validator.errorList.length) {
list.empty();
container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
$.each(validator.errorList, function () {
$("<li />").html(this.message).appendTo(list);
});
}
}
If you really want to you can unbind the jquery.validate.unobtrusive
handler like this - but i wouldn't bother myself
$("form").unbind("invalid-form.validate"); // unbind default MS handler
If you're wondering why this works
$("form").data("validator").settings.submitHandler = ...
and this doesn't work
$("form").data("validator").settings.invalidHandler = ...
it's because submitHandler
is explicily called inside jquery.validate
when validation is performed. Therefore it doesn't matter at what point it is set.
validator.settings.submitHandler.call( validator, validator.currentForm );
but the invalidHandler
is bound to an event during init()
like this so if you set it in your own code it is too late
if (this.settings.invalidHandler)
$(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
A little stepping through code makes for a lot of understanding sometimes! Hope this helps
*Make sure you don't have minification in bundles enabled.
handleSubmit()
is called only if all form values validate. It is not called if you have any errors. It's perfect for asking for confirmation like you are (because you know everything is valid) but if you want special handling when there are errors you must useinvalidHandler
- see DGreen's answer – BetainejQuery.validator.setDefaults
directly and any subsequent form intializations will use those settings. Just make sure it runs before the DOM is loaded and jQuery Validator automatically initializes the forms. – Anthozoan