-1

I have a group of checkboxes defined as follows:

<label>What is your favorite color?</label>
<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test1" name="test">
  <label class="custom-control-label" for="test1">Red</label>
</div>

<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test2" name="test">
  <label class="custom-control-label" for="test2">Green</label>
</div>

<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test3" name="test">
  <label class="custom-control-label" for="test3">Neither</label>
</div>

How can I make one of them to be selected required in a form? Thanks!!

Makyen
  • 31,849
  • 12
  • 86
  • 121
  • when any checkbox is checked/unchecked, exam anyone of them are checked. if yes, show/enable the submit button. if not, disallow the user to proceed. – Sphinx Jun 30 '20 at 23:47
  • This is trying to replicate functionality of radios. Why not just use radios and use *"required"* attribute? – charlietfl Jun 30 '20 at 23:54
  • 1
    Does this answer your question? [html select only one checkbox in a group](https://stackoverflow.com/questions/9709209/html-select-only-one-checkbox-in-a-group) – ikiK Jun 30 '20 at 23:54
  • https://stackoverflow.com/questions/6218494/using-the-html5-required-attribute-for-a-group-of-checkboxes https://stackoverflow.com/questions/22238368/how-can-i-require-at-least-one-checkbox-be-checked-before-a-form-can-be-submitte same questions already answered here on SO. – ikiK Jun 30 '20 at 23:55

6 Answers6

1

When the form is submitted, loop through all the checkboxes and verify that at least one is checked using Array#some; otherwise, prevent the default action.

const checkboxes = [...document.querySelectorAll("input[name=test]")];
document.querySelector('button').addEventListener("click", function(e){
  if(!checkboxes.some(({checked})=>checked)){
    document.querySelector("input").setCustomValidity('Please choose a color.');
  }
});
<form>
<label>What is your favorite color?</label>
<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test1" name="test">
  <label class="custom-control-label" for="test1">Red</label>
</div>

<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test2" name="test" >
  <label class="custom-control-label" for="test2">Green</label>
</div>

<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test3" name="test">
  <label class="custom-control-label" for="test3">Neither</label>
</div>
<button>Submit</button>
</form>

Since it seems that you only want one to be selected, you can use the required attribute and make them radio buttons.

<form>
<label>What is your favorite color?</label>
<div class="custom-control custom-checkbox">
  <input type="radio" class="custom-control-input" id="test1" name="test" required>
  <label class="custom-control-label" for="test1">Red</label>
</div>

<div class="custom-control custom-checkbox">
  <input type="radio" class="custom-control-input" id="test2" name="test" required>
  <label class="custom-control-label" for="test2">Green</label>
</div>

<div class="custom-control custom-checkbox">
  <input type="radio" class="custom-control-input" id="test3" name="test" required>
  <label class="custom-control-label" for="test3">Neither</label>
</div>
<button>Submit</button>
</form>
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
0

When a submit button is clicked, call a javascript function which will check if one of the checkboxes is checked. If yes, then let them proceed, otherwise

event.preventDefault();
MeetuU
  • 185
  • 1
  • 12
0

I guess this is what you're looking for:


var verifyPaymentType = function () {
  var checkboxes = $('.wish_payment_type .checkbox');
  var inputs = checkboxes.find('input');
  var first = inputs.first()[0];

  inputs.on('change', function () {
    this.setCustomValidity('');
  });

  first.setCustomValidity(checkboxes.find('input:checked').length === 0 ? 'Choose one' : '');
}

$('#submit').click(verifyPaymentType);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<form id="processForm.php" action="post">
  <div class="input check_boxes required wish_payment_type">
    <div class="wish_payment_type">
    <span class="checkbox payment-radio">
      <label for="wish_payment_type_1">
        <input class="check_boxes required" id="wish_payment_type_1" name="wish[payment_type][]" type="checkbox" value="1">Foo
      </label>
    </span>
    <span class="checkbox payment-radio">
      <label for="wish_payment_type_2">
        <input class="check_boxes required" id="wish_payment_type_2" name="wish[payment_type][]" type="checkbox" value="2">Bar
      </label>
    </span>
    <span class="checkbox payment-radio">
      <label for="wish_payment_type_3">
        <input class="check_boxes required" id="wish_payment_type_3" name="wish[payment_type][]" type="checkbox" value="3">Buzz
      </label>

      <input id='submit' type="submit" value="Submit">
  </div>
</form>
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
Umutambyi Gad
  • 4,082
  • 3
  • 18
  • 39
0

function handleSubmit(e) {
  function warning(set) {
    e.preventDefault();
    console.log("checkbox required", set);
  }
  //index values dependent on input count + sequence
  let isCheckedA = [0, 1, 2].map(i => e.target[i].checked).some(checked => !!checked);

  let isCheckedB = [3, 4, 5].map(i => e.target[i].checked).some(checked => !!checked);

  if (!isCheckedA) warning("A");
  if (!isCheckedB) warning("B");
}
<form onsubmit="handleSubmit(event)">
  <label>What is your favorite color?</label>
  <div class="custom-control custom-checkbox">
    <input type="checkbox" class="custom-control-input" id="test1" name="test">
    <label class="custom-control-label" for="test1">Red</label>
  </div>

  <div class="custom-control custom-checkbox">
    <input type="checkbox" class="custom-control-input" id="test2" name="test">
    <label class="custom-control-label" for="test2">Green</label>
  </div>

  <div class="custom-control custom-checkbox">
    <input type="checkbox" class="custom-control-input" id="test3" name="test">
    <label class="custom-control-label" for="test3">Neither</label>
  </div>
  <label>What is your favorite fruit?</label>
  <div class="custom-control custom-checkbox">
    <input type="checkbox" class="custom-control-input" id="test4" name="test">
    <label class="custom-control-label" for="test15">Apple</label>
  </div>

  <div class="custom-control custom-checkbox">
    <input type="checkbox" class="custom-control-input" id="test5" name="test">
    <label class="custom-control-label" for="test5">Orange</label>
  </div>

  <div class="custom-control custom-checkbox">
    <input type="checkbox" class="custom-control-input" id="test6" name="test">
    <label class="custom-control-label" for="test6">Neither</label>
  </div>
  <input type="submit" />
</form>
Pavlos Karalis
  • 2,893
  • 1
  • 6
  • 14
0

Here is a version using js

const submit_btn = document.getElementById('submit')
submit_btn.disabled = true

const checkboxs = document.getElementsByClassName("custom-control-input")

function checkChanged() {
  overall_check = false
  for (let i = 0; i < checkboxs.length; i++) {
    if (checkboxs[i].checked) {
      overall_check = true;
      break;
    }
  }
  if (overall_check)
    submit_btn.disabled = false
  else
   submit_btn.disabled = true
}

// Register click Listener 
for (let i = 0; i < checkboxs.length; i++) {
  checkboxs[i].addEventListener("change", checkChanged)
}
<label>What is your favorite color?</label>
<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test1" name="test">
  <label class="custom-control-label" for="test1">Red</label>
</div>

<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test2" name="test">
  <label class="custom-control-label" for="test2">Green</label>
</div>

<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test3" name="test">
  <label class="custom-control-label" for="test3">Neither</label>
</div>
<button id="submit">Submit</button>

Here is a version using jquery. Should be polished a bit IMO

all_check_boxes = $('.custom-control-input')
$('#submit').prop('disabled', true)

$('.custom-control-input').on('change', () => {
  checked = false
  all_check_boxes.each(function( index ) {
    if ($(this).is(':checked')) {
      checked = true;
    }
  });
  
  if (checked) {
    $('#submit').prop('disabled', false)
  } else {
    $('#submit').prop('disabled', true)
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label>What is your favorite color?</label>
<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test1" name="test">
  <label class="custom-control-label" for="test1">Red</label>
</div>

<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test2" name="test">
  <label class="custom-control-label" for="test2">Green</label>
</div>

<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="test3" name="test">
  <label class="custom-control-label" for="test3">Neither</label>
</div>
<button id="submit">Submit</button>
Supun De Silva
  • 1,437
  • 9
  • 15
  • This is good, but I was wondering if there way to show a pop up or something. Similar to @Gad's answer –  Jul 02 '20 at 20:03
0

While there is plenty of answers I will just chip in with my solution that uses HTML required attribute for native browser notifications.

As I see none of the answers use that, some use disable button and some disable form etc.

required is set from the start on all elements and if one checkbox is checked required is removed from all, if its set back to unchecked it sets all back to required.

var form = document.getElementById('myForm');
var els = document.querySelectorAll('input[name="test"]');

form.onchange = function() {
      for (var i = 0, len = els.length; i < len; i++) {
        [].forEach.call(els, function(el) {
          el.required = true;;
        });
      };
      
  for (var i = 0; i < els.length; i++) {
    if (els[i].checked) {
      for (var i = 0, len = els.length; i < len; i++) {
        [].forEach.call(els, function(el) {
          el.removeAttribute("required");
        });
      };
    } 
  }
};
form.onchange();
<form>
  <div id="myForm">
    <label>What is your favorite color?</label>
    <div class="custom-control custom-checkbox">
      <input type="checkbox" class="custom-control-input" id="test1" name="test" required>
      <label class="custom-control-label" for="test1">Red</label>
    </div>

    <div class="custom-control custom-checkbox">
      <input type="checkbox" class="custom-control-input" id="test2" name="test" required>
      <label class="custom-control-label" for="test2">Green</label>
    </div>

    <div class="custom-control custom-checkbox">
      <input type="checkbox" class="custom-control-input" id="test3" name="test" required>
      <label class="custom-control-label" for="test3">Neither</label>
    </div>
    <button type="submit">Submit</button>
    <div>
      <form>

And now you got HTML radio buttons :)

ikiK
  • 6,328
  • 4
  • 20
  • 40
  • Will give this a shot! Thanks!! –  Jul 02 '20 at 20:03
  • It's not as great as some would think because the browser will, when user attempts to submit the form without having checked any of the required checkboxes, confuse the user by flagging the first checkbox that is required as invalid and displaying an alert next to that particular checkbox along the lines of that that particular checkbox has to be checked -- that's confusing, as it's not that checkbox that must be checked, necessarily, but any checkbox in the group. – Armen Michaeli May 02 '21 at 10:31