This is something of an odd one. There are many questions on SO in regard to setting the ignore
property for unobtrusive validation's settings
object.
The scenario: I have a table generated by iterating over a model in MVC and I auto-populate a blank row at the bottom by inserting a blank model at the server side (it's part of the requirements, non-negotiable). I don't want to validate this blank row if the user hasn't touched it but do if they have.
To solve this, I generate the table as normal. Using jquery, I auto mark any blank rows with a class of "blank". I can see this happening only for blank rows in the table by viewing the source.
Now, if in the document.read() call on the client I have;
$.validator.unobtrusive.parse('form');
var form = $('form').get(0);
var settings = $.data(form, 'validator').settings;
settings.ignore = ':hidden,.blank';
This works just fine. Hitting submit will not trigger validation on blank rows even when I add new ones. However, validation doesn't happen on any of the populated rows apart from the first row.
To solve this, I created a function reattachValidation()
that is called whenever I add a new row so that validation will trigger for the new rows. The code was modified to:
function reattachValidation() {
var forms = $('form');
forms.removeData('validator');
forms.removeData('unobtrusiveValidation');
$.validator.unobtrusive.parse('form');
var form = $('form').get(0);
var settings = $.data(form, 'validator').settings;
settings.ignore = ':hidden,.blank';
}
Now the code above will validate any new rows dynamically added to the table but will also validate the blank rows which still have a class of "blank" on the relevant elements. So I can either not validate blank rows and no new rows OR I can validate all rows including those with elements tagged with "blank".
How can I ignore the blank rows while also validating the new rows with user data?
I did eventually get this working.
In javascript;
$(function() {
$.validator.unobtrusive.parse("form");
var form = $("form").get(0);
var settings = $.data(form, "validator").settings;
settings.ignore = ":hidden,.blank";
});
// This function will attach any dynamic entity (e.g., a new row in a grid) to the
// MVC unobtrusive validator to be validated at the appropriate time.
// Usage: $.validator.unobtrusive.parseDynamicContent(newTableRow);
(function ($) {
$.validator.unobtrusive.parseDynamicContent = function (selector) {
//use the normal unobstrusive.parse method
$.validator.unobtrusive.parse(selector);
//get the relevant form
var form = $(selector).closest("form");
//get the collections of unobtrusive validators, and jquery validators
//and compare the two
var unobtrusiveValidation = form.data("unobtrusiveValidation");
var validator = form.validate();
$.each(unobtrusiveValidation.options.rules, function (elname, elrules) {
if (validator.settings.rules[elname] == undefined) {
var args = {};
$.extend(args, elrules);
args.messages = unobtrusiveValidation.options.messages[elname];
//edit:use quoted strings for the name selector
$("[name='" + elname + "']").rules("add", args);
} else {
$.each(elrules, function (rulename, data) {
if (validator.settings.rules[elname][rulename] == undefined) {
var args = {};
args[rulename] = data;
args.messages = unobtrusiveValidation.options.messages[elname][rulename];
//edit:use quoted strings for the name selector
$("[name='" + elname + "']").rules("add", args);
}
});
}
});
}
})($);
Then when adding the new dynamic elements, this was done like so (animation is unnecessary but the call to parseDynamicContent()
is;
selectedTableRow.after(newTableRow);
newTableRow.fadeIn(500, function () {
// reattach the MVC validation after adding a new row so that we get our client
// side validation on the data annotations.
// NOTE: we do this AFTER the fade in animation as by default the validator will
// not hook into any hidden elements - which our row is until the animation
// completes.
$.validator.unobtrusive.parseDynamicContent(newTableRow);
});