Is it possible to get jquery validation to show the validation summary using eager validation?
I'm using MVC 3 (if it matters) and my forms validate when each element loses focus:
$('#myform').validate({ onfocusout: function(element) { $(element).valid(); } };
This shows individual errors on each field, however I also want to show those errors in the validation summary block. However, that validation summary only shows up when the form is submitted, not on lost focus.
I've tried hooking into showErrors, however that only gives me the current field error, not the current list of errors.
For completeness, here's the form code:
@using (Ajax.BeginForm(...))
{
<div class="field-panel">
@Html.EditorFor(m => m.PatientID)
...
</div>
<input type="submit" class="carecon-button-next" value="Next" />
@Html.ValidationSummary(null, new { @class = "validation-summary" })
}
Ok, I think I figured this out.
The issue is actually due to using the unobtrusive validation with MVC 3, since it does the jQuery validation initialization for you Thus the only way to configure validation is by using form.data("validator").settings
. However, trying to set the errorLabelContainer
via this method, i.e.:
$("#form").data("validator").settings.errorLabelContainer = "#messageBox";
... doesn't work, because jQuery's validation only uses this value internally in it's init() function, to configure a bunch of other settings like containers , etc. I tried emulating what it does, or even calling $("#form").data("validator").init()
again after setting the errorLabelContainer
, but doing so caused weird behavior and hosed a bunch of other settings.
So I took a different approach. First, I provided a place for MVC to put in the individual error strings using @Html.ValidationMessageFor()
, and adding display:none
to keep it hidden:
@using (Ajax.BeginForm(...))
{
<div class="field-panel">
@Html.EditorFor(m => m.PatientID)
@Html.ValidationMessageFor(m => m.PatientID, null, new { style = "display:none"})
...
</div>
<input type="submit" class="carecon-button-next" value="Next" />
<ul id="error-summary">
</ul>
}
Then, in the showErrors
callback, I copy those strings in to the validation summary after calling defaultShowErrors()
:
$("#form").data("validator").settings.onfocusout = function (element) { $(element).valid(); };
$("#form").data("validator").settings.showErrors = function (errorMap, errorList) {
this.defaultShowErrors();
$("#error-summary").empty();
$(".field-validation-error span", $("#form"))
.clone()
.appendTo("#error-summary")
.wrap("<li>");
};
This gave me the behavior I wanted, showing/hiding the validation errors as a list in the summary as the user filled out the fields on the form.
I was having similar troubles and wrote this, it seems like an easy way to get the behavior you are looking for:
function EnableEagerValidation(){
var itemsNeedingValidation = $('*[data-val="true"]');
itemsNeedingValidation.each(function () {
$(this).blur(function(){$(this).closest("form").valid();});
});
}
This is from the demo page; the invalidHandler
and the code to create an error summary. But it's triggered on form
submit which is not what you requested.
invalidHandler: function(e, validator) {
var errors = validator.numberOfInvalids();
if (errors) {
var message = errors == 1
? 'You missed 1 field. It has been highlighted below'
: 'You missed ' + errors + ' fields. They have been highlighted below';
$("div.error span").html(message);
$("div.error").show();
} else {
$("div.error").hide();
}
},
However, the errorLabelContainer:
method does not require form
submission. As per the documentation, "All error labels are displayed inside an unordered list with the ID "messageBox", as specified by the selector passed as errorContainer option. All error elements are wrapped inside an li element, to create a list of messages."
errorLabelContainer: "#messageBox",
Here is a crude demo showing validation using onfocusout
. There is no submit button to prove this point. The #messageBox
accumulates all the messages as they are collected.
http://jsfiddle.net/sparky672/bAN2Q/