Disable a button if no checkboxes are clicked

Viewed 150

I have multiple checkboxes on a page, generated with PHP. How would I go about creating a javascript script that would disable a button if NONE of the checkboxes are clicked, and enable the button if even ONE of the boxes are clicked? I'm brand new to Javascript, so I'm sure this is relatively easy, but any help would be so greatly appreciated.

Here's what I have so far, but this only works for one checkbox, and not multiple.

Javascript:

function terms_changed(termsCheckBox){
    if(termsCheckBox.checked){
        document.getElementById("submit_button").disabled = false;
    } else{
        document.getElementById("submit_button").disabled = true;
    }
}

HTML:

<form method="post">
    <div>
        <input type='checkbox' name='uuid[]' value=1 id=1 onclick="terms_changed(this)"/>
        <input type='checkbox' name='uuid[]' value=2 id=2 onclick="terms_changed(this)"/>
        <input type='checkbox' name='uuid[]' value=3 id=3 onclick="terms_changed(this)"/>
        /// plus countless others, you get the idea ///
    </div>
    <div>
        <button type="submit" id="submit_button" disabled>Sign Up</button>
    </div>
</form>
5 Answers

You would need to iterate over all checkboxes to see if any are checked each time. Or you can use a selector for it like this:

function terms_changed(termsCheckBox){
       document.getElementById("submit_button").disabled = !termsCheckBox.parentElement.querySelectorAll("input[type=checkbox]:checked").length;
   }
<html>
<form method="post">
    <div>
        <input type='checkbox' name='uuid[]' value=1 id=1 onclick="terms_changed(this)"/>
        <input type='checkbox' name='uuid[]' value=2 id=2 onclick="terms_changed(this)"/>
        <input type='checkbox' name='uuid[]' value=3 id=3 onclick="terms_changed(this)"/>
    </div>
    <div>
        <button type="submit" id="submit_button" disabled>Sign Up</button>
    </div>
</form>
</html>

// get parent element which is a div and then get all checkboxes
// check if any of them is checked.
function terms_changed(termsCheckBox) {
  document.getElementById("submit_button").disabled = !([...termsCheckBox.parentElement.querySelectorAll("input[type=checkbox]")].some(cb => cb.checked));
}
<form method="post">
    <div>
        <input type='checkbox' name='uuid[]' value=1 id=1 onclick="terms_changed(this)"/>
        <input type='checkbox' name='uuid[]' value=2 id=2 onclick="terms_changed(this)"/>
        <input type='checkbox' name='uuid[]' value=3 id=3 onclick="terms_changed(this)"/>
        /// plus countless others, you get the idea ///
    </div>
    <div>
        <button type="submit" id="submit_button" disabled>Sign Up</button>
    </div>
</form>

Made some minor changes to the HTML, the attribute values should be in quotes, for example: id="cb1"

You can avoid using an onclick attribute on every checkbox by using event delegation that checks the whole form on any click. This can be streamlined to check more specifically, perhaps using [name="uuid[]"]

document.getElementById("frm").addEventListener("click", function(evt) {
  let checked = 0;
  this.querySelectorAll('input[type="checkbox"]').forEach(e => {
    if (e.checked) checked++;});
  document.getElementById("submit_button").disabled = checked === 0;
  // add code in here to identify which checkbox was clicked based on the id
  alert(evt.target.id + " was clicked");
});
<form id="frm" method="post">
  <div>
    <input type='checkbox' name='uuid[]' value="1" id="cb1">
    <input type='checkbox' name='uuid[]' value="2" id="cb2">
    <input type='checkbox' name='uuid[]' value="3" id="cb3"> /// plus countless others, you get the idea ///
  </div>
  <div>
    <button type="submit" id="submit_button" disabled>Sign Up</button>
  </div>
</form>

If there's a slight chance to reformat HTML, you could apply this functionality only with CSS. Hence I'll post my answer since it differs from all the JS solutions offered here:

button {
  background-color: #c0c0c0;
  color: GrayText;
  border: 2px outset ButtonFace;
  pointer-events: none;
}

input:checked ~ div > button {
  background-color: #a0c0a0;
  color: #333333;
  pointer-events: auto;
  cursor: pointer;
}
<form>
  <input type='checkbox' />
  <input type='checkbox' />
  <input type='checkbox' />
  <div>
    <button>Go</button>
  </div>
</form>

With a bit of reactive programming fun:

  • Each click(...) return a stream that emits a boolean after each click. True if the checkbox is checked, false otherwise. Starts with false.
  • Combine all streams into one. It emits the status of all checkboxes every time one changes.
  • Disable button if all checkboxes are unticked.

const {combineLatest, fromEvent} = rxjs;
const {startWith, map} = rxjs.operators;

const el = sel => document.querySelector(sel);

const click =
  sel =>
    fromEvent(el(sel), 'click')
      .pipe( map(ev => ev.target.checked === true)
           , startWith(false)
           );
      
stream$ =
  combineLatest
    ( click('#cb1')
    , click('#cb2')
    , click('#cb3')
    , click('#cb4')
    , click('#cb5')
    );

stream$.subscribe(checked => {
  const btn = el('button');
  btn.disabled = checked.every(c => c === false);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.3/rxjs.umd.min.js" integrity="sha512-JnZPWAckMDks0CCIeGznqEo7ifmYK7VowHq/NVFlSXGkwxv4OBCJFy7nouOtJZmVldHo7FQLIdeWTI55yyZc4Q==" crossorigin="anonymous"></script>

<input type="checkbox" id="cb1">
<input type="checkbox" id="cb2">
<input type="checkbox" id="cb3">
<input type="checkbox" id="cb4">
<input type="checkbox" id="cb5">
<button>Sign Up</button>

Related