JQuery Validate – can I re-validate a group of fields after changing one

jqueryjquery-validate

I'm using jQuery Validate and would like to re-validate a group of fields whenever one of them is changed (or possibly, whenever one of them validates successfully). My attempts so far just create infinite loops.

Is this possible, or does the plugin design preclude it?

(Specifically, I've got a method that requires at least X of group Y to be filled out, and as soon as that's true, I'd like all those fields to re-validate. Currently I'm clearing out their error messages with my own code, but that's a hack – it also hides unrelated validation problems until the form is re-submitted.)

Best Answer

The validate method has a few options to support re-validating on change, namely these:

$(".selector").validate({
  onfocusout: true,
  onkeyup: true,
  onclick: true,
  //The rest of your options
});

These all default to false, but should offer the functionality you mention in the question.

Update based on comments: Given a simple test form like this:

<form action="get">
    <div><input type="text" name="part1" class="part"></div>
    <div><input type="text" name="part2" class="part"></div>
    <div><input type="text" name="part3" class="part"></div>
    <div><input type="text" name="part4" class="part"></div>
    <input type="submit" value="Submit" />
</form>

The jQuery would be the following:

jQuery.validator.addMethod("require_from_group", function(value, element, options) {
    var valid = $(options[1], element.form).filter(function() {
        return $(this).val();
    }).length >= options[0];

    if(!$(element).data('reval')) {
        var fields = $(options[1], element.form);
        fields.data('reval', true).valid();
        fields.data('reval', false);
    }
    return valid;
}, jQuery.format("Please fill out at least {0} of these fields."));

$("form").validate({
    rules: {
        part1: { require_from_group: [2,".part"] },
        part2: { require_from_group: [2,".part"] },
        part3: { require_from_group: [2,".part"] },
        part4: { require_from_group: [2,".part"] }
    }
});​

You can play with a demo here, see if this is what you're after: http://jsfiddle.net/mhmBs/

The method here uses .data() to let an element know not to cause an infinite loop. The actual element that is being edited, on blur (normal cause for validation triggers) re-validates only the other elements in the selector you specified in the group, so not the whole form like my comment...it's only triggering it on the minimum number of elements. ​