3

I've a very complex form with X groups of checkboxes like this:

<div class="checkbox-block1">
 <input id="package-1-1" name="member[1][package][19]" type="checkbox" class="checkbox" value="100" style="float: left;">
 <input id="package-1-2" name="member[1][package][234]" type="checkbox" class="checkbox" value="300" style="float: left;">
 <input id="package-1-3" name="member[1][package][254]" type="checkbox" class="checkbox" value="500" style="float: left;">
</div>
<div class="checkbox-block2">
 <input id="package-2-1" name="member[2][package][19]" type="checkbox" class="checkbox" value="100" style="float: left;">
 <input id="package-2-2" name="member[2][package][234]" type="checkbox" class="checkbox" value="300" style="float: left;">
 <input id="package-2-3" name="member[2][package][254]" type="checkbox" class="checkbox" value="500" style="float: left;">
</div>

I need to validate the form with a rules that require at least on checkbox for group/block. I try with:

      $(document).ready(function () {
            $("#myform-s3").validate({
                rules: {
                    'member[1]': {
                        required: true,
                        minlength: 1
                    },
                    'member[2]': {
                        required: true,
                        minlength: 1
                    },
                    'member[3]': {
                        required: true,
                        minlength: 1
                    }
                },
                errorPlacement: function(error, element) {
                    if ( element.is(':radio') || element.is(':checkbox') ) {
                        error.insertBefore( element.next() );
                    } else {
                        error.insertAfter( element );
                    }
                },
                submitHandler: function (form) { // for demo
                    alert('valid form');
                    return false;
                }
            });

But I got "Valid Form" also when no checkbox is selected.

P.S: Number of blocks are selected by the user in a previous form, then I can have 1, 2, 3 or more blocks of checkboxes.

Sparky
  • 98,165
  • 25
  • 199
  • 285
natas
  • 456
  • 2
  • 9
  • 15

1 Answers1

3

Your code...

rules: {
    'member[1]': {  // <- MUST be the NAME of input element

member[1] is not the name of anything so nothing is going to happen. You cannot use partial names or selectors here, just the actual value of the name attribute.


Solution 1

To validate a group of checkboxes, you need them all to share the same name...

<div class="checkbox-block1">
    <input id="package-1-1" name="member[1]" type="checkbox" class="checkbox" value="100" style="float: left;">
    <input id="package-1-2" name="member[1]" type="checkbox" class="checkbox" value="300" style="float: left;">
    <input id="package-1-3" name="member[1]" type="checkbox" class="checkbox" value="500" style="float: left;">
</div>

And then you can simply use the required rule all by itself...

$(document).ready(function () {
    $("#myform-s3").validate({
        rules: {
            'member[1]': {
                required: true
            }, ....

DEMO 1: https://jsfiddle.net/1an60fxy/


Solution 2

If you cannot alter the naming, then you must dynamically declare the rules using the .rules() method and a "starts with", ^=, selector.

Do not declare the rules within .validate()...

$(document).ready(function () {
    $("#myform-s3").validate({
        rules: {
            // other fields maybe
        ....

Use the .rules() method with an .each() and the required_from_group rule. Note, required_from_group is part of the additional-methods.js file.

$('[name^="member[1]"]').each(function() {
    $(this).rules('add', {
        require_from_group: [1, $('[id^="package-1"]')]
    });
});

Where 1 is the minimum number required from the group and $('[id^="package-1"]') targets all members of the group.

DEMO 2: jsfiddle.net/1an60fxy/2/

With this version, you get duplicated messages that you will have to handle with the groups option. Since your form is complex and dynamic, you will need to construct this option dynamically before you call .validate(). Here is an example.

var names1 = ""; // create empty string
$('[id^="package-1"]').each(function() { // grab each input starting w/ the class
    names1 += $(this).attr('name') + " "; // append each name + single space to string
});
names1 = $.trim(names1); // remove the empty space from the end

$("#myform-s3").validate({
    groups: {
        myGroup: names1 // reference the string
    }, 
    ....

DEMO 2b: jsfiddle.net/1an60fxy/3/

Sparky
  • 98,165
  • 25
  • 199
  • 285
  • Uhm, I'll try your solution later, for now thanks, but then I need to scroll the groups with a for to check every blocks of checkbox? – natas May 31 '18 at 17:00
  • @natas, there's no other way. You either make the `name` conform to `required` OR you use `require_from_group` and will have to deal with duplicate messages. – Sparky May 31 '18 at 17:02