56

I have a list of multiple check boxes. The user can check all of them, but at least one should be checked to allow form submission. How can I enforce that requirement?

<p>Box Set 1</p>
<ul>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 1" required><label>Box 1</label></li>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 2" required><label>Box 2</label></li>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 3" required><label>Box 3</label></li>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 4" required><label>Box 4</label></li>
</ul>
<p>Box Set 2</p>
<ul>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 5" required><label>Box 5</label></li>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 6" required><label>Box 6</label></li>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 7" required><label>Box 7</label></li>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 8" required><label>Box 8</label></li>
</ul>
<p>Box Set 3</p>
<ul>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 9" required><label>Box 9</label></li>
</ul>
<p>Box Set 4</p>
<ul>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 10" required><label>Box 10</label></li>
</ul>
TylerH
  • 20,799
  • 66
  • 75
  • 101
Jeff Morrris
  • 671
  • 1
  • 5
  • 8
  • You could use PHP to check if at least 1 of the check boxes is checked. You would probably also want to make sure your is different for each check box otherwise getting the return variable values might be tricky. – TheShinyTuxedo Mar 06 '14 at 23:29
  • Had similar problem. Solved with: http://stackoverflow.com/a/37825072/1479143 – thegauraw Jun 15 '16 at 02:33

11 Answers11

67

Here's an example using jquery and your html.

$(document).ready(function () {
    $('#checkBtn').click(function() {
        checked = $("input[type=checkbox]:checked").length;

        if(!checked) {
            alert("You must check at least one checkbox.");
            return false;
        }
    });
});
<html>
    <head>
         <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
    </head>
    <body>
        <p>Box Set 1</p>
        <ul>
            <li><input name="BoxSelect[]" type="checkbox" value="Box 1" required><label>Box 1</label></li>
            <li><input name="BoxSelect[]" type="checkbox" value="Box 2" required><label>Box 2</label></li>
            <li><input name="BoxSelect[]" type="checkbox" value="Box 3" required><label>Box 3</label></li>
            <li><input name="BoxSelect[]" type="checkbox" value="Box 4" required><label>Box 4</label></li>
        </ul>
        <p>Box Set 2</p>
        <ul>
            <li><input name="BoxSelect[]" type="checkbox" value="Box 5" required><label>Box 5</label></li>
            <li><input name="BoxSelect[]" type="checkbox" value="Box 6" required><label>Box 6</label></li>
            <li><input name="BoxSelect[]" type="checkbox" value="Box 7" required><label>Box 7</label></li>
            <li><input name="BoxSelect[]" type="checkbox" value="Box 8" required><label>Box 8</label></li>
        </ul>
        <p>Box Set 3</p>
        <ul>
            <li><input name="BoxSelect[]" type="checkbox" value="Box 9" required><label>Box 9</label></li>
        </ul>
        <p>Box Set 4</p>
        <ul>
            <li><input name="BoxSelect[]" type="checkbox" value="Box 10" required><label>Box 10</label></li>
        </ul>
        <input type="button" value="Test Required" id="checkBtn">
    </body>
</html>
Benjamin Buch
  • 4,752
  • 7
  • 28
  • 51
Jason R
  • 2,085
  • 20
  • 12
46

Make all the checkboxes required and add a change listener. If any one checkbox is ticked, remove required attribute from all the checkboxes. Below is a sample code.

<div class="form-group browsers">
    <label class="control-label col-md-4" for="optiontext">Select an option</label>
    <div class="col-md-6">
        <input type="checkbox" name="browser" value="Chrome" required/> Google Chrome<br>
        <input type="checkbox" name="browser" value="IE" required/> Internet Explorer<br>
        <input type="checkbox" name="browser" value="Mozilla" required/> Mozilla Firefox<br>
        <input type="checkbox" name="browser" value="Edge" required/> Microsoft Edge
    </div>
</div>

Change listener :

$(function(){
    var requiredCheckboxes = $('.browsers :checkbox[required]');
    requiredCheckboxes.change(function(){
        if(requiredCheckboxes.is(':checked')) {
            requiredCheckboxes.removeAttr('required');
        } else {
            requiredCheckboxes.attr('required', 'required');
        }
    });
});
lepe
  • 24,677
  • 9
  • 99
  • 108
Harshita Sethi
  • 2,035
  • 3
  • 24
  • 46
  • 2
    So simple and well understandable amongst all answers! – Miron Oct 26 '20 at 08:52
  • Are there any accessibility issues with having the form load with all inputs `required` by default when they're not actually all required? – aronmoshe_m Feb 04 '21 at 22:48
  • Excellent thank you - works perfectly! I did find that '.change' has now been deprecated so I replaced it with '.on' in case anyone has the same problem! – CallyB Apr 29 '21 at 19:34
  • A in my opinion notable drawback of flagging all (or any of) checkboxes with the `required` attribute is that if the user attempts to submit the [invalid] form, the user agent (e.g. Chrome) may tell the user to "please check this box if you want to proceed", which may be a misleading message for some specific random checkbox, usually the first in the list. It's not that the user must select *that* (first) checkbox, it's just that they have to select one in the list. So the UX doesn't really match the design here. – Armen Michaeli May 02 '21 at 10:19
  • @amn In that case, you can change the message shown when form is submitted and checkbox is not ticked.. you can change the text using `setCustomValidity(text)` in the `oninvalid` event. You can refer this link for changing the message https://stackoverflow.com/questions/10361460/how-can-i-change-or-remove-html5-form-validation-default-error-messages – Harshita Sethi May 03 '21 at 04:59
  • 4
    It won't help much -- the problem will be the user agent will flag some checkbox control as invalid, with invalid control notification shown next to the checkbox -- even if the notification text doesn't mention the specific checkbox, the user will be inclined to think it is _that_ checkbox they have to tick, which is the root of the problem here -- they don't have to check the checkbox that the user agent flags them as "invalid", they have to tick any in the group. – Armen Michaeli May 03 '21 at 08:50
  • 1
    A better idea is to check for this condition with the `submit` event handler, and flag _some group element_ as valid/invalid according to whether any checkbox is ticked or not. Alternatively -- because there aren't any group controls that are well suited for this kind of validation (fieldset elements cannot be flagged as invalid, for instance), just produce your own markup that communicates invalid condition, foregoing use of `setCustomValidity`. Also don't forget to call `preventDefault` on the `submit` event if no checkboxes are ticked. – Armen Michaeli May 03 '21 at 08:53
6
<ul>
    <li><input class="checkboxes" name="BoxSelect[]" type="checkbox" value="Box 1" required><label>Box 1</label></li>
    <li><input class="checkboxes" name="BoxSelect[]" type="checkbox" value="Box 2" required><label>Box 2</label></li>
    <li><input class="checkboxes" name="BoxSelect[]" type="checkbox" value="Box 3" required><label>Box 3</label></li>
    <li><input class="checkboxes" name="BoxSelect[]" type="checkbox" value="Box 4" required><label>Box 4</label></li>
</ul>

<script type="text/javascript">
$(document).ready(function(){
    var checkboxes = $('.checkboxes');
    checkboxes.change(function(){
        if($('.checkboxes:checked').length>0) {
            checkboxes.removeAttr('required');
        } else {
            checkboxes.attr('required', 'required');
        }
    });
});
</script>
Erhan Rden
  • 231
  • 1
  • 3
  • 7
5

This should have what you need, check out the jsfiddle at the bottom:

$(document).ready(function() {
    $('#txt').val($("input[type=checkbox]:checked").length);
    $('#txt2').val($("input[type=checkbox]").length);

    $('input[type=checkbox]').change(function() {
        checked = $("input[type=checkbox]:checked").length;
        $('#block').show();
        $('#block2').hide();
        if (checked > 0) {
            $('#block').hide();
            $('#block2').show();
            $('#txt').val(checked);
        }
    });
});
lepe
  • 24,677
  • 9
  • 99
  • 108
stackPusher
  • 6,076
  • 3
  • 35
  • 36
  • What happens if Javascript is disabled? – Dynelight Mar 06 '14 at 23:35
  • +1 because javascript/jQuery is easier/makes more sense than using PHP. It's better to check before the form is even submitted. – Alexander Lozada Mar 06 '14 at 23:45
  • 1
    ...but thinking of Dynelight's comment below, it'd be even better to use both so nobody can fool you if they fiddle with their javascript. – Alexander Lozada Mar 06 '14 at 23:56
  • I do need to check on submit. There is lots of other data going and I would have to pass it back or they would have to start over. – Jeff Morrris Mar 07 '14 at 00:07
  • How do I put an else in the js if none are checked and stop the form from sending? if (checked > 0) { $('#block').hide(); $('#block2').show(); $('#txt').val(checked); } else { check box not checked } – Jeff Morrris Mar 07 '14 at 00:09
2

The issue with the accepted solution above is that is does not allow for the else condition on form submit (if a box has been selected), thereby preventing form submission - at least when I tried it.

I discovered another solution that effects the desired result more completely IMHO, here:

Making sure at least one checkbox is checked

Code as follows:

function valthis() {
    var checkBoxes = document.getElementsByClassName('myCheckBox');
    var isChecked = false;
    for (var i = 0; i < checkBoxes.length; i++) {
        if (checkBoxes[i].checked) {
            isChecked = true;
        };
    };
    if (isChecked) {
        alert('At least one checkbox checked!');
    } else {
        alert('Please, check at least one checkbox!');
    }
}

Fiddle

That code & answer by Vell

lepe
  • 24,677
  • 9
  • 99
  • 108
collyg
  • 171
  • 1
  • 7
1

For php, when you use checkboxes for multiple values, the name always ends with []. We can use this to make the solution a bit more generic. And, since I put my error message in a data-message-value-missing attribute, I use:

$form.on('change', 'input[type=checkbox][name$="[]"]', e => {
    const $inputs = $('input[type=checkbox][name="' + e.target.name + '"]');
    const $targetInp = $inputs.filter('[data-message-value-missing]');
    if ($inputs.filter(':checked').length) {
        $targetInp.removeAttr('required');
        $form.find('label.error').html('');
    } else {
        $targetInp.attr('required', 'required');
    }
});

To make this work, set the data-message-value-missing and the required on only one (the last) input:

<ul>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 1"><label>Box 1</label></li>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 2"><label>Box 2</label></li>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 3"><label>Box 3</label></li>
   <li><input name="BoxSelect[]" type="checkbox" value="Box 4" required data-message-value-missing="Select at least one"><label>Box 4</label></li>
</ul>

I excluded the code to handle the checkValidity(), etc. Seems beyond the scope of this question...

lepe
  • 24,677
  • 9
  • 99
  • 108
mous
  • 331
  • 1
  • 9
1

I have read some other solutions to this, but they all suffer from a number of disadvantages, in my opinion, one or several of the following:

  1. User agent will communicate about some particular checkbox when that checkbox or all checkboxes are marked up as required or when the checkbox is explicitly flagged as invalid with setCustomValidity. The result is confusing to the user as the user agent does its earnest clearly communicating to the user that the user must check that particular checkbox to proceed, which isn't what you'd want anyway -- you merely want the user to check any checkbox in the group, in the very least.

  2. Flagging checkboxes as valid/invalid when checking and unchecking these is also a bit of a UX dead end -- you will need to validate the form containing these at submission anyway, even when the user hasn't touched any of the checkboxes once prior to attempting to submit the form -- how are you validating the form? Marking checkboxes as required to ensure at least one gets checked before form may be submitted gets you the aforementioned problem, again.

In light of these drawbacks, I, for one, have used the following approach:

form.addEventListener("submit", ev => {
    if(!Array.prototype.some.call(checkboxes(), checkbox => checkbox.checked)) {
        tell_user_they_must_check_some_checkbox(); /// Instead of `setCustomValidity` which we can't use since we don't have a single particular checkbox to flag as invalid, just implement our own notification
        ev.preventDefault(); /// Prevent form submission -- the "submit" event only fires if the form was validated successfully in the first place, so it's up to us to stop the submission (according to our own validation constraints that cannot be expressed with `required` on some form controls).
    }
});

That's all I think there is to it. I left out selection of actual checkboxes since that's not the point the code is trying to illustrate, but you'll have to define the group of checkboxes you want to validate with the above by implementing checkboxes. It can be a generator function or simply one that returns the array or some HTML collection of these.

The important thing is that setCustomValidity can't meaningfully be used at all since there is no way to flag some group or at least contextually appropriate control of the form as invalid. If you find one, like some submit button, for example, the tell_user_they_must_check_some_checkbox reduces to a setCustomValidity call. You still need to prevent default because there won't be any checking of actually invalid controls after the "submit" event has been processed, that happens before, so we need to abort submission ourselves, if applicable.

As an exercise to the reader, you can implement grouping with some data- attributes or just grouping implicitly by containing the checkboxes where you want at least one in the group selected, in a fieldset (or even a div or whatever) and checking against those grouped -- like I said, which checkboxes you want to select for validating against the aforementioned condition, is entirely up to the form designer. You can even experiment with identical name for all grouped checkboxes, much like is done with radio buttons to good effect, but that may break traditional form submission (multiple checkboxes with the same name may not be serialized by the user agent into a POST request as you'd want them to be)

Armen Michaeli
  • 8,625
  • 8
  • 58
  • 95
0

You can either do this on a PHP level or on a Javascript level. If you use Javascript, and/or JQuery, you can check and validate if all the checkboxes are checked with a selector...

Jquery also offers several validation libraries. Check out: http://jqueryvalidation.org/

The problem with using Javascript to validate is that it may be bypassed so it is wise to check on the server too.

Example using PHP and assuming you are calling a PO

<?php
if( $_GET["BoxSelect"] ) {
     //Process your form here
     // Save to database, send email, redirect...
} else {
     // Return an error and do not anything
     echo "Checkbox is missing"; 
     exit();
}
?>
lepe
  • 24,677
  • 9
  • 99
  • 108
Dynelight
  • 2,072
  • 4
  • 25
  • 50
  • 3
    What if they aren't using php? You should do _both_. Use javascript because it will give a faster validation response and save web server resources, but back it up with your server platform language because you can't trust the user's browser. – Joel Coehoorn Mar 30 '17 at 15:45
0

Using this you can check at least one checkbox is selected or not in different checkbox groups or multiple checkboxes.

Reference : Link

<label class="control-label col-sm-4">Check Box 1</label>
    <input type="checkbox" name="checkbox1" id="checkbox1" value=Male /> Male<br />
    <input type="checkbox" name="checkbox1" id="checkbox1" value=Female /> Female<br />

<label class="control-label col-sm-4">Check Box 2</label>
    <input type="checkbox" name="checkbox2" id="checkbox2" value=ck1 /> ck1<br />
    <input type="checkbox" name="checkbox2" id="checkbox2" value=ck2 /> ck2<br />

<label class="control-label col-sm-4">Check Box 3</label>
    <input type="checkbox" name="checkbox3" id="checkbox3" value=ck3 /> ck3<br />
    <input type="checkbox" name="checkbox3" id="checkbox3" value=ck4 /> ck4<br />

<script>
function checkFormData() {
    if (!$('input[name=checkbox1]:checked').length > 0) {
        document.getElementById("errMessage").innerHTML = "Check Box 1 can not be null";
        return false;
    }
    if (!$('input[name=checkbox2]:checked').length > 0) {
        document.getElementById("errMessage").innerHTML = "Check Box 2 can not be null";
        return false;
    }
    if (!$('input[name=checkbox3]:checked').length > 0) {
        document.getElementById("errMessage").innerHTML = "Check Box 3 can not be null";
        return false;
    }
    alert("Success");
    return true;
}
</script>
Parth Patel
  • 799
  • 1
  • 13
  • 20
0

function isAtleastCheckInputChecked(selector){
    
    var inputGroup = document.querySelectorAll(selector);

    if(inputGroup == undefined){
        return false;
    }

    var isChecked = false;

    inputGroup.forEach(        
        function(currentValue, currentIndex, listObj) {
            if(currentValue.checked){
                isChecked = true;
            }
        }
    );

    return isChecked;
}

function validateForm(evt){

  validationStatus = isAtleastCheckInputChecked("input[name='desiredpositionchecks']");
  
  if(validationStatus){
    //looks good, can proceed for further procesing form data.
    document.querySelector("#validationStatus").innerText = "valid form";
    
  }
  else{
  //form is not valid
  document.querySelector("#validationStatus").innerText = "invalid form";
  }

}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">    
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
   
</head>
<body>
<div class="col-md border-end col-sm-4 py-2">
                            <label for="firstName" class="form-label">DESIRED POSITION<sup style="color: red;">*</sup></label>
                              <div class="form-check">
                                <input class="form-feild form-check-input" type="checkbox" name="desiredpositionchecks" value="1" id="goalKeeperCheck" aria-describedby="desiredpositionchecks">
                                <label class="form-check-label" for="goalKeeperCheck">
                                  GOAL KEEPER
                                </label>                                
                              </div>
                              <div class="form-check">
                                <input class="form-feild form-check-input" type="checkbox" name="desiredpositionchecks" value="2" id="offensiveCheck" aria-describedby="desiredpositionchecks">
                                <label class="form-check-label" for="offensiveCheck">
                                  OFFENSIVE
                                </label>
                              </div>
                              <div class="form-check">
                                <input class="form-feild form-check-input" type="checkbox" name="desiredpositionchecks" value="3" id="defenseCheck" aria-describedby="desiredpositionchecks">
                                <label class="form-check-label" for="defenseCheck">
                                  DEFENSE
                                </label>
                              </div>
                              <div class="form-check">
                                <input class="form-feild form-check-input" type="checkbox" name="desiredpositionchecks" value="4" id="receiverCheck" aria-describedby="desiredpositionchecks">
                                <label class="form-check-label" for="receiverCheck">
                                  RECEIVER
                                </label>
                                <div id="desiredpositionchecks" class="feedback invalid-feedback">Please select a valid feild.</div>
                              </div>            
                            
                        </div>
                        <div class="col" id="validationStatus"></div>
                        <div class="col-md-4 text-center">
                            <button type="button" id="form-submit" name="form-submit" class="btn btn-primary" onclick="validateForm(event)">Check Validation</button>
                        </div>
                        
                            <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>    
    
</body>
</html>
Paramjot Singh
  • 627
  • 4
  • 8
0

If you have more than one checkbox / radio group in your page, you can validate that at least one is checked by using the name attribute:

$('#new-user-form').submit(function(e) {

  let roleChecked = $("input[name='NewUser.RolesArray']:checked").length;

  if (!roleChecked) {
    console.log("You must check at least one Role.");
    e.preventDefault();
    return false;
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="new-user-form" method="post">
    <div class="form-horizontal new-user">

        <div class="form-group">
            <h3 class="required">Roles</h3>
            <div class="roles h200">
                <div>
                    <label>
                        <input type="checkbox" name="NewUser.RolesArray" value="Academic Coordinator">
                        Academic Coordinator
                    </label>
                </div>
                <div>
                    <label>
                        <input type="checkbox" name="NewUser.RolesArray" value="Human Resources">
                        Human Resources
                    </label>
                </div>
                <div>
                    <label>
                        <input type="checkbox" name="NewUser.RolesArray" value="Support Technician">
                        Support Technician
                    </label>
                </div>
                <div>
                    <label>
                        <input type="checkbox" name="NewUser.RolesArray" value="Student">
                        Student
                    </label>
                </div>
                <div>
                    <label>
                        <input type="checkbox" name="NewUser.RolesArray" value="Director">
                        Director
                    </label>
                </div>
                <div>
                    <label>
                        <input type="checkbox" name="NewUser.RolesArray" value="Administrator">
                        Administrator
                    </label>
                </div>
                <div>
                    <label>
                        <input type="checkbox" name="NewUser.RolesArray" value="Finance">
                        Finance
                    </label>
                </div>
                <div>
                    <label>
                        <input type="checkbox" name="NewUser.RolesArray" value="Manager">
                        Manager
                    </label>
                </div>
                <div>
                    <label>
                        <input type="checkbox" name="NewUser.RolesArray" value="Modify Attendance">
                        Modify Attendance
                    </label>
                </div>
                <div>
                    <label>
                        <input type="checkbox" name="NewUser.RolesArray" value="Attendance">
                        Attendance
                    </label>
                </div>
                <div>
                    <label>
                        <input type="checkbox" name="NewUser.RolesArray" value="Teacher">
                        Teacher
                    </label>
                </div>
            </div>
        </div>
        <hr>
        <div class="required">Required</div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" id="create-button">
            </div>
        </div>
    </div>
</form>