[html] html select only one checkbox in a group

So how can I only allow a user to select only one checkbox?

I know radio buttons are "ideal", but for my purpose...it's not.

I have a field where users need to select either or of the two options, but not both. The problem is that I need my users to also be able to unselect their option, and this is where radio buttons fail because once you select the group, you have to choose an option.

I will be validating the info via php, but I'd still like to restrict the users to one answer if they want to give it.

This question is related to html checkbox

The answer is


Here is a simple HTML and JavaScript solution I prefer:

//js function to allow only checking of one weekday checkbox at a time:

function checkOnlyOne(b){

var x = document.getElementsByClassName('daychecks');
var i;

for (i = 0; i < x.length; i++) {
  if(x[i].value != b) x[i].checked = false;
}
}


Day of the week:
<input class="daychecks" onclick="checkOnlyOne(this.value);" type="checkbox" name="reoccur_weekday" value="Monday" />Mon&nbsp;&nbsp;&nbsp;
<input class="daychecks" onclick="checkOnlyOne(this.value);" type="checkbox" name="reoccur_weekday" value="Tuesday" />Tue&nbsp;&nbsp;&nbsp;
<input class="daychecks" onclick="checkOnlyOne(this.value);" type="checkbox" name="reoccur_weekday" value="Wednesday" />Wed&nbsp;&nbsp;&nbsp;
<input class="daychecks" onclick="checkOnlyOne(this.value);" type="checkbox" name="reoccur_weekday" value="Thursday" />Thu&nbsp;&nbsp;&nbsp;
<input class="daychecks" onclick="checkOnlyOne(this.value);" type="checkbox" name="reoccur_weekday" value="Friday" />Fri&nbsp;&nbsp;&nbsp;
<input class="daychecks" onclick="checkOnlyOne(this.value);" type="checkbox" name="reoccur_weekday" value="Saturday" />Sat&nbsp;&nbsp;&nbsp;
<input class="daychecks" onclick="checkOnlyOne(this.value);" type="checkbox" name="reoccur_weekday" value="Sunday" />Sun&nbsp;&nbsp;&nbsp;<br /><br />

Necromancing:
And without jQuery, for a checkbox structure like this:

<label>
<input type="checkbox" id="mytrackers_1" name="blubb_1" value="">--- Bitte ausw&#228;hlen ---
</label>
<label>
<input type="checkbox" id="mytrackers_2" name="blubb_2" value="7">Testtracker
</label>
<label>
<input type="checkbox" id="mytrackers_3" name="blubb_3" value="3">Kundenanfrage
</label>
<label>
<input type="checkbox" id="mytrackers_4" name="blubb_4" value="2">Anpassung
</label>
<label>
<input type="checkbox" id="mytrackers_5" name="blubb_5" value="1" checked="checked" >Fehler
</label>
<label>
<input type="checkbox" id="mytrackers_6" name="blubb_6" value="4">Bedienung
</label>
<label>
<input type="checkbox" id="mytrackers_7" name="blubb_7" value="5">Internes
</label>
<label>
<input type="checkbox" id="mytrackers_8" name="blubb_8" value="6">&#196;nderungswunsch
</label>

you would do it like this:

    /// attach an event handler, now or in the future, 
    /// for all elements which match childselector,
    /// within the child tree of the element maching parentSelector.
    function subscribeEvent(parentSelector, eventName, childSelector, eventCallback) {
        if (parentSelector == null)
            throw new ReferenceError("Parameter parentSelector is NULL");
        if (childSelector == null)
            throw new ReferenceError("Parameter childSelector is NULL");
        // nodeToObserve: the node that will be observed for mutations
        var nodeToObserve = parentSelector;
        if (typeof (parentSelector) === 'string')
            nodeToObserve = document.querySelector(parentSelector);
        var eligibleChildren = nodeToObserve.querySelectorAll(childSelector);
        for (var i = 0; i < eligibleChildren.length; ++i) {
            eligibleChildren[i].addEventListener(eventName, eventCallback, false);
        } // Next i 
        // https://stackoverflow.com/questions/2712136/how-do-i-make-this-loop-all-children-recursively
        function allDescendants(node) {
            if (node == null)
                return;
            for (var i = 0; i < node.childNodes.length; i++) {
                var child = node.childNodes[i];
                allDescendants(child);
            } // Next i 
            // IE 11 Polyfill 
            if (!Element.prototype.matches)
                Element.prototype.matches = Element.prototype.msMatchesSelector;
            if (node.matches) {
                if (node.matches(childSelector)) {
                    // console.log("match");
                    node.addEventListener(eventName, eventCallback, false);
                } // End if ((<Element>node).matches(childSelector))
                // else console.log("no match");
            } // End if ((<Element>node).matches) 
            // else console.log("no matchfunction");
        } // End Function allDescendants 
        // Callback function to execute when mutations are observed
        var callback = function (mutationsList, observer) {
            for (var _i = 0, mutationsList_1 = mutationsList; _i < mutationsList_1.length; _i++) {
                var mutation = mutationsList_1[_i];
                // console.log("mutation.type", mutation.type);
                // console.log("mutation", mutation);
                if (mutation.type == 'childList') {
                    for (var i = 0; i < mutation.addedNodes.length; ++i) {
                        var thisNode = mutation.addedNodes[i];
                        allDescendants(thisNode);
                    } // Next i 
                } // End if (mutation.type == 'childList') 
                // else if (mutation.type == 'attributes') { console.log('The ' + mutation.attributeName + ' attribute was modified.');
            } // Next mutation 
        }; // End Function callback 
        // Options for the observer (which mutations to observe)
        var config = { attributes: false, childList: true, subtree: true };
        // Create an observer instance linked to the callback function
        var observer = new MutationObserver(callback);
        // Start observing the target node for configured mutations
        observer.observe(nodeToObserve, config);
    } // End Function subscribeEvent 


    function radioCheckbox_onClick() 
    { 
        // console.log("click", this);
        let box = this;
        if (box.checked) 
        {
            let name = box.getAttribute("name");
            let pos = name.lastIndexOf("_");
            if (pos !== -1) name = name.substr(0, pos);

            let group = 'input[type="checkbox"][name^="' + name + '"]';
            // console.log(group);
            let eles = document.querySelectorAll(group);
            // console.log(eles);
            for (let j = 0; j < eles.length; ++j) 
            {
                eles[j].checked = false;
            }
            box.checked = true;
        }
        else
            box.checked = false;
    }


    // https://stackoverflow.com/questions/9709209/html-select-only-one-checkbox-in-a-group
    function radioCheckbox()
    { 
        // on instead of document...
        let elements = document.querySelectorAll('input[type="checkbox"]')

        for (let i = 0; i < elements.length; ++i)
        {
            // console.log(elements[i]);
            elements[i].addEventListener("click", radioCheckbox_onClick, false);

        } // Next i 

    } // End Function radioCheckbox 


    function onDomReady()
    {
        console.log("dom ready");
        subscribeEvent(document, "click", 
            'input[type="checkbox"]', 
            radioCheckbox_onClick
        ); 

        // radioCheckbox();
    }

    if (document.addEventListener) document.addEventListener("DOMContentLoaded", onDomReady, false);
    else if (document.attachEvent) document.attachEvent("onreadystatechange", onDomReady);
    else window.onload = onDomReady;

    function onPageLoaded() {
        console.log("page loaded");
    }

    if (window.addEventListener) window.addEventListener("load", onPageLoaded, false);
    else if (window.attachEvent) window.attachEvent("onload", onPageLoaded);
    else window.onload = onPageLoaded;

Checkbox Group

_x000D_
_x000D_
var group_=(el,callback)=>{
el.forEach((checkbox)=>{
callback(checkbox)
     })
}

group_(document.getElementsByName('check'),(item)=>{
item.onclick=(e)=>{
group_(document.getElementsByName('check'),(item)=>{
item.checked=false;
})
e.target.checked=true;

}
})
_x000D_
<input type="checkbox" name="check" >
<input type="checkbox" name="check" >
<input type="checkbox" name="check" >
<input type="checkbox" name="check">
_x000D_
_x000D_
_x000D_

checkbox simple without loop

_x000D_
_x000D_
var last;
document.addEventListener('input',(e)=>{
if(e.target.getAttribute('name')=="myRadios"){
if(last)
last.checked=false;
}
e.target.checked=true;
last=e.target;
})
_x000D_
<input type="checkbox" name="myRadios" value="1" /> 1
<input type="checkbox" name="myRadios" value="2" /> 2
_x000D_
_x000D_
_x000D_

Group By Single Div

_x000D_
_x000D_
var group_=(el,callback)=>{
el.forEach((checkbox)=>{
callback(checkbox)
     })
}
var group_el=document.querySelectorAll("*[data-name] > input")
group_(group_el,(item)=>{
item.onclick=(e)=>{
group_(group_el,(item)=>{
item.checked=false;
})

e.target.checked=true;
}
})
_x000D_
<div data-name="check">
<input type="checkbox">
<input type="checkbox">
<input type="checkbox">
<input type="checkbox">
</div>
_x000D_
_x000D_
_x000D_

css single group div

_x000D_
_x000D_
var last;
document.addEventListener('input',(e)=>{
var closest=e.target.closest("*[data-name='check']");
console.log(closest)
if(e.target.closest("*[data-name]")){
if(last)
last.checked=false;
}

e.target.checked=true;
last=e.target;
})
_x000D_
<div data-name="check">
<input type="checkbox" value="1" /> 1
<input type="checkbox" value="2" /> 2
</div>
_x000D_
_x000D_
_x000D_ check ,uncheck and single checked box
_x000D_
_x000D_
var last;
document.addEventListener('input',(e)=>{
var closest=e.target.closest("*[data-name='check']");
if(e.target.closest("*[data-name]")){
if(last)
last.checked=false;
}
if(e.target!==last)
last=e.target;
else
last=undefined;
})
_x000D_
<div data-name="check">
<input type="checkbox" value="1" /> 1
<input type="checkbox" value="2" /> 2
</div>
_x000D_
_x000D_
_x000D_


Radio buttons are ideal. You just need a third "neither" option that is select by default.


May this code helps you.

_x000D_
_x000D_
$(document).ready(function(){_x000D_
$('.slectOne').on('change', function() {_x000D_
   $('.slectOne').not(this).prop('checked', false);_x000D_
   $('#result').html($(this).data( "id" ));_x000D_
   if($(this).is(":checked"))_x000D_
    $('#result').html($(this).data( "id" ));_x000D_
   else_x000D_
    $('#result').html('Empty...!');_x000D_
});_x000D_
});
_x000D_
<!DOCTYPE html>_x000D_
<html>_x000D_
<head>_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>_x000D_
_x000D_
</head>_x000D_
<body>_x000D_
<input type="checkbox" class="slectOne" data-id="1 selected"/>_x000D_
<input type="checkbox" class="slectOne" data-id="2 selected"/>_x000D_
<input type="checkbox" class="slectOne" data-id="3 selected"/>_x000D_
<input type="checkbox" class="slectOne" data-id="4 selected"/>_x000D_
<input type="checkbox" class="slectOne" data-id="5 selected"/>_x000D_
<input type="checkbox" class="slectOne" data-id="6 selected"/>_x000D_
<input type="checkbox" class="slectOne" data-id="7 selected"/>_x000D_
<input type="checkbox" class="slectOne" data-id="8 selected"/>_x000D_
<input type="checkbox" class="slectOne" data-id="9 selected"/>_x000D_
<input type="checkbox" class="slectOne" data-id="10 selected"/>_x000D_
<span id="result"></span>_x000D_
</body>_x000D_
</html>
_x000D_
_x000D_
_x000D_

Working link Click here


Building up on billyonecan's answer, you can use the following code if you need that snippet for more than one checkbox (assuming they have different names).

    $('input.one').on('change', function() {
        var name = $(this).attr('name');
        $('input[name='+name+'].one').not(this).prop('checked', false);
    }); 

You'd want to bind a change() handler so that the event will fire when the state of a checkbox changes. Then, just deselect all checkboxes apart from the one which triggered the handler:

$('input[type="checkbox"]').on('change', function() {
   $('input[type="checkbox"]').not(this).prop('checked', false);
});

Here's a fiddle


As for grouping, if your checkbox "groups" were all siblings:

<div>
    <input type="checkbox" />
    <input type="checkbox" />
    <input type="checkbox" />
</div>  
<div>
    <input type="checkbox" />
    <input type="checkbox" />
    <input type="checkbox" />
</div>   
<div>
    <input type="checkbox" />
    <input type="checkbox" />
    <input type="checkbox" />
</div>

You could do this:

$('input[type="checkbox"]').on('change', function() {
   $(this).siblings('input[type="checkbox"]').prop('checked', false);
});

Here's another fiddle


If your checkboxes are grouped by another attribute, such as name:

<input type="checkbox" name="group1[]" />
<input type="checkbox" name="group1[]" />
<input type="checkbox" name="group1[]" />

<input type="checkbox" name="group2[]" />
<input type="checkbox" name="group2[]" />
<input type="checkbox" name="group2[]" />

<input type="checkbox" name="group3[]" />
<input type="checkbox" name="group3[]" />
<input type="checkbox" name="group3[]" />

You could do this:

$('input[type="checkbox"]').on('change', function() {
    $('input[name="' + this.name + '"]').not(this).prop('checked', false);
});

Here's another fiddle


My version: use data attributes and Vanilla JavaScript

<div class="test-checkbox">
    Group One: <label>
        <input type="checkbox" data-limit="only-one-in-a-group" name="groupOne" value="Eat" />Eat</label>
    <label>
        <input type="checkbox" data-limit="only-one-in-a-group" name="groupOne" value="Sleep" />Sleep</label>
    <label>
        <input type="checkbox" data-limit="only-one-in-a-group" name="groupOne" value="Play" />Play</label>
    <br />
    Group Two: <label>
        <input type="checkbox" data-limit="only-one-in-a-group" name="groupTwo" value="Fat" />Fat</label>
    <label>
        <input type="checkbox" data-limit="only-one-in-a-group" name="groupTwo" value="Comfort" />Comfort</label>
    <label>
        <input type="checkbox" data-limit="only-one-in-a-group" name="groupTwo" value="Happy" />Happy</label>
</div>
<script>
    let cbxes = document.querySelectorAll('input[type="checkbox"][data-limit="only-one-in-a-group"]');
    [...cbxes].forEach((cbx) => {
        cbx.addEventListener('change', (e) => {
            if (e.target.checked)
                uncheckOthers(e.target);
        });
    });
    function uncheckOthers (clicked) {
        let name = clicked.getAttribute('name');
        // find others in same group, uncheck them
        [...cbxes].forEach((other) => {
            if (other != clicked && other.getAttribute('name') == name)
                other.checked = false;
        });
    }
</script>

There are already a few answers to this based on pure JS but none of them are quite as concise as I would like them to be.

Here is my solution based on using name tags (as with radio buttons) and a few lines of javascript.

_x000D_
_x000D_
function onlyOne(checkbox) {_x000D_
    var checkboxes = document.getElementsByName('check')_x000D_
    checkboxes.forEach((item) => {_x000D_
        if (item !== checkbox) item.checked = false_x000D_
    })_x000D_
}
_x000D_
<input type="checkbox" name="check" onclick="onlyOne(this)">_x000D_
<input type="checkbox" name="check" onclick="onlyOne(this)">_x000D_
<input type="checkbox" name="check" onclick="onlyOne(this)">_x000D_
<input type="checkbox" name="check" onclick="onlyOne(this)">
_x000D_
_x000D_
_x000D_


While JS is probably the way to go, it could be done with HTML and CSS only.

Here you have a fake radio button which is really a label for a real hidden radio button. By doing that, you get exactly the effect you need.

<style>
   #uncheck>input { display: none }
   input:checked + label { display: none }
   input:not(:checked) + label + label{ display: none } 
</style>

<div id='uncheck'>
  <input type="radio" name='food' id="box1" /> 
  Pizza 
    <label for='box1'>&#9678;</label> 
    <label for='box0'>&#9673;</label>
  <input type="radio" name='food' id="box2" /> 
  Ice cream 
    <label for='box2'>&#9678;</label> 
    <label for='box0'>&#9673;</label>
  <input type="radio" name='food' id="box0" checked />
</div>

See it here: https://jsfiddle.net/tn70yxL8/2/

Now, that assumes you need non-selectable labels.

If you were willing to include the labels, you can technically avoid repeating the "uncheck" label by changing its text in CSS, see here: https://jsfiddle.net/7tdb6quy/2/


Example With AngularJs

_x000D_
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>_x000D_
<!DOCTYPE html>_x000D_
<html>_x000D_
_x000D_
<head>_x000D_
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>_x000D_
  <script>_x000D_
    angular.module('app', []).controller('appc', ['$scope',_x000D_
      function($scope) {_x000D_
        $scope.selected = 'other';_x000D_
      }_x000D_
    ]);_x000D_
  </script>_x000D_
</head>_x000D_
_x000D_
<body ng-app="app" ng-controller="appc">_x000D_
  <label>SELECTED: {{selected}}</label>_x000D_
  <div>_x000D_
    <input type="checkbox" ng-checked="selected=='male'" ng-true-value="'male'" ng-model="selected">Male_x000D_
    <br>_x000D_
    <input type="checkbox" ng-checked="selected=='female'" ng-true-value="'female'" ng-model="selected">Female_x000D_
    <br>_x000D_
    <input type="checkbox" ng-checked="selected=='other'" ng-true-value="'other'" ng-model="selected">Other_x000D_
  </div>_x000D_
_x000D_
_x000D_
_x000D_
</body>_x000D_
_x000D_
</html>
_x000D_
_x000D_
_x000D_


$("#myform input:checkbox").change(function() {
    $("#myform input:checkbox").attr("checked", false);
    $(this).attr("checked", true);
});

This should work for any number of checkboxes in the form. If you have others that aren't part of the group, set up the selectors the applicable inputs.


If someone need a solution without an external javascript libraries you could use this example. A group of checkboxes allowing 0..1 values. You may click on the checkbox component or associated label text.

    <input id="mygroup1" name="mygroup" type="checkbox" value="1" onclick="toggleRadioCheckbox(this)" /> <label for="mygroup1">Yes</label>
    <input id="mygroup0" name="mygroup" type="checkbox" value="0" onclick="toggleRadioCheckbox(this)" /> <label for="mygroup0">No</label>

- - - - - - - - 

    function toggleRadioCheckbox(sender) {
        // RadioCheckbox: 0..1 enabled in a group 
        if (!sender.checked) return;
        var fields = document.getElementsByName(sender.name);
        for(var idx=0; idx<fields.length; idx++) {
            var field = fields[idx];
            if (field.checked && field!=sender)
                field.checked=false;
        }
    }

_x000D_
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>_x000D_
<!DOCTYPE html>_x000D_
<html>_x000D_
_x000D_
<head>_x000D_
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>_x000D_
  <script>_x000D_
    angular.module('app', []).controller('appc', ['$scope',_x000D_
      function($scope) {_x000D_
        $scope.selected = 'male';_x000D_
      }_x000D_
    ]);_x000D_
  </script>_x000D_
</head>_x000D_
_x000D_
<body ng-app="app" ng-controller="appc">_x000D_
  <label>SELECTED: {{selected}}</label>_x000D_
  <div>_x000D_
    <input type="checkbox" ng-checked="selected=='male'" ng-true-value="'male'" ng-model="selected">Male_x000D_
    <br>_x000D_
    <input type="checkbox" ng-checked="selected=='female'" ng-true-value="'female'" ng-model="selected">Female_x000D_
    <br>_x000D_
    <input type="checkbox" ng-checked="selected=='other'" ng-true-value="'other'" ng-model="selected">Other_x000D_
  </div>_x000D_
</body>_x000D_
</html>
_x000D_
_x000D_
_x000D_


With plain old javascript.

<html>
<head>
</head>
<body>
<input type="checkbox" name="group1[]" id="groupname1" onClick="toggle(1,'groupname')"/>
<input type="checkbox" name="group1[]" id="groupname2" onClick="toggle(2,'groupname')"  />
<input type="checkbox" name="group1[]" id="groupname3" onClick="toggle(3,'groupname')" />

<input type="checkbox" name="group2[]" id="diffGroupname1" onClick="toggle(1,'diffGroupname')"/>
<input type="checkbox" name="group2[]" id="diffGroupname2" onClick="toggle(2,'diffGroupname')"  />
<input type="checkbox" name="group2[]" id="diffGroupname3" onClick="toggle(3,'diffGroupname')" />
<script>
function toggle(which,group){
var counter=1;
var checkbox=document.getElementById(group+counter);
while(checkbox){
if(counter==which){

}else{
checkbox.checked=false;
}
counter++;
checkbox=document.getElementById(group+counter);
}
}
</script>
</body>
</html>

edit: also possible

<html>
<head>
</head>
<body>
<input type="checkbox" name="group1[]" class="groupname" onClick="toggle(this,'groupname')"/>
<input type="checkbox" name="group1[]" class="groupname" onClick="toggle(this,'groupname')"  />
<input type="checkbox" name="group1[]" class="groupname" onClick="toggle(this,'groupname')" />

<input type="checkbox" name="group2[]" class="diffGroupname" onClick="toggle(this,'diffGroupname')"/>
<input type="checkbox" name="group2[]" class="diffGroupname" onClick="toggle(this,'diffGroupname')"  />
<input type="checkbox" name="group2[]" class="diffGroupname" onClick="toggle(this,'diffGroupname')" />
<script>
function toggle(which,theClass){
var checkbox=document.getElementsByClassName(theClass);
for(var i=0;i<checkbox.length;i++){
if(checkbox[i]==which){

}else{
checkbox[i].checked=false;
}
}
}
</script>
</body>
</html>

The Code snippet below demonstrates a simple approach for selecting only one checkbox in a group.


_x000D_
_x000D_
  <!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
    <h3>Demonstration of Checkbox Toggle</h3>
    <p>
        <span><b>Letters:</b></span>
        A<input type="checkbox" name="A" >
        B<input type="checkbox" name="B" >
        C<input type="checkbox" name="C" >
        D<input type="checkbox" name="D" >
    </p>
    <p>
        <span><b>Numbers:</b></span>
        1<input type="checkbox" name="1" >
        2<input type="checkbox" name="2" >
        3<input type="checkbox" name="3" >
    </p>
     <p>
        <span><b>Birds:</b></span>
        Scarlet Ibis<input type="checkbox" name="Scarlet Ibis" >
        Cocrico <input type="checkbox" name="Cocrico" >
        hummingbird <input type="checkbox" name="hummingbird" >
    </p>
</body>

<script>
    $(function()
    {
        function toggle(choices,name) 
        {
            if(choices.includes(name))
            {
                for( i=0;i<choices.length;i++)
                {
                if(name !=choices[i])
                    $('input[name="' + choices[i] + '"]').not(this).prop('checked', false); 
                }
            }
        }
        $('input[type="checkbox"]').on('change', function() 
        {
            var letters = ["A","B","C","D"];
            var numbers = ["1", "2", "3"];
            var birds = ["Scarlet Ibis", "Cocrico", "hummingbird"];
            
            toggle(letters,this.name);
            toggle(numbers,this.name);
            toggle(birds,this.name);
        });

    });
</script>
</html>
_x000D_
_x000D_
_x000D_


//Here is a solution using JQuery    
<input type = "checkbox" class="a"/>one
    <input type = "checkbox" class="a"/>two
    <input type = "checkbox" class="a"/>three
    <script>
       $('.a').on('change', function() {
            $('.a').not(this).prop('checked',false);
    });
    </script>