views:

490

answers:

1

I've put together a form using the jQuery Validation plugin, and all inputs are fine with working validation and error messages – except for checkboxes. I have two checkbox problems.

The first is that the Validation plugin API doesn't seem to handle checkboxes in grouped contexts (I'm using fieldsets for grouping). Found several approaches to the issue here, including reference to a post by Rebecca Murphey for a more general case using a custom method and class. Adapting that to this situation:

jQuery.validator.addMethod('required_group', function(val, el) {
        var fieldParent = $(el).closest('fieldset');
        return fieldParent.find('.required_group:checked').length;
});

jQuery.validator.addClassRules('required_group', {
        'required_group': true
});

jQuery.validator.messages.required_group = 'Please check at least one box.';

This sort of works, but produces error messages on every checkbox, and only removes them as each box is clicked. This is not an acceptable situation for the user, who can only get rid of them by clicking false positives. Ideally, I guess what's needed is something to prevent or eliminate extra messages before they are displayed and use errorPlacement to display a single error message in the parent fieldset, that would then be removed with a click on any checkbox. Less ideally, maybe they would all display but an event handler could turn off the full set of redundant messages with a click, which is what this approach offered by tvanfosson appears to do. (Another customized approach here, but I couldn't get it to work.) I guess I should also note this form requires the checkboxes to have different names.

My second problem is that one of the fieldsets with checkboxes in the form also contains a nested fieldset of checkboxes under one of the outer checkboxes. So in addition to the first-level one-box-checked requirement, if the particular checkbox containing the second-level checkboxes is checked, then at least one of the second-level boxes must be checked. Not sure about the right approach; I'm guessing what needs to happen (following the above scheme) is that the trigger checkbox would use toggleClass to add/remove 'required_group' class to all the checkboxes in the subfield, which would then (hopefully) behave the same as the parent field:

$("#triggerCheckbox").click(function () {
  $(this).find(":checkbox").toggleClass("required_group");
});

Any suggestions or ideas welcome. I'm well beyond my limited jQuery skills on this one and would be happy to hear that I missed simple, elegant and/or obvious ways to do this!

+1  A: 

I have dealt with a similar problem before, although in my specific case I think I had it easier than you - I had the groups of checkboxes, but nothing else in the form needed validating.

Here's the general idea, which may solve your problem of "one error per checkbox":

//for each fieldset, attach a new rule to the first checkbox
$('fieldset input[type="checkbox"]:first').each(function(i,v){
    $(v).rules('add', {
         required: "fieldset input[type="checkbox"]:unchecked"
    });
});

In order to do something sane with the validation errors, implement your own showErrors function. Here's where the simplicity of my case probably won't help you much - I didn't have to worry about whether the errors were in a checkbox group or not, in my form if there were any errors, it would be the same problem - at least one checkbox wasn't checked per fieldset. For you, I think you would have to dig into Validate plugin's defaultShowErrors function (in the source) to see what to do with the errorMap and errorList.

$('#myForm').validate({
   ...
   showErrors: function(map,list){
       if (this.numberofInvalids()){
           $('#form_errors').html('You much choose at least one Checkbox per group');
       } else {
           this.defaultShowErrors();
       }
   }
 });

For the 2nd part of your question, I imagine a 'depends' rule is what you're looking for. So no need to actually add classes, just have a the rule for the sub-group be a depends on the parent checkbox being checked (see the almost perfect example in the rules method docs).

Ryley
Yeah, I did solve my issue in creating special errorPlacement and I did force the user to fill the first 2 fields. If he does not, then I use my errorPlacement for the 2 cases (but theerrorPlacment was another issue specific to my file upload inputs). Cheers.
Nicolas