Recipe 7.9

Validating a Checkbox Group

This example shows how to use custom validation to require that at least one checkbox in a group is checked.

Demo

Select one or more options:

Code

JavaScript
const form = document.querySelector('#options-form');

function validateCheckboxes(form) {
  const data = new FormData(form);

  // To avoid setting the validation error on multiple elements,
  // choose the first checkbox and use that to hold the group's validation
  // message.
  const element = form.elements.option1;

  if (!data.has('options')) {
    element.setCustomValidity('Please select at least one option.');
  } else {
    element.setCustomValidity('');
  }
}

/**
 * Adds the necessary event listeners to an element to participate in form validation.
 * It handles setting and clearing error messages depending on the validation state.
 * @param element The input element to validate
 * @param errorId The ID of a placeholder element that will show the error message
 */
function addValidation(element, errorId) {
  const errorElement = document.getElementById(errorId);

  /**
   * Fired when the form is validated and the field is not valid.
   * Sets the error message and style.
   */
  element.addEventListener('invalid', () => {
    errorElement.textContent = element.validationMessage;
  });

  /**
   * Fired when user input occurs in the field.
   * It will re-check the field's validity and clear the error message if it becomes valid.
   */
  element.addEventListener('change', () => {
    validateCheckboxes(form);
    if (form.elements.option1.checkValidity()) {
      errorElement.textContent = '';
    }
  });
}

addValidation(form.elements.option1, 'checkbox-error');
addValidation(form.elements.option2, 'checkbox-error');
addValidation(form.elements.option3, 'checkbox-error');

form.addEventListener('submit', event => {
  event.preventDefault();
  validateCheckboxes(form);
  console.log(form.checkValidity());
});
HTML
<form id="options-form" novalidate>
  <p>Select one or more options:</p>
  <div class="form-check">
    <input class="form-check-input" type="checkbox" name="options" value="option1" id="option1">
    <label class="form-check-label" for="option1">
      Option 1
    </label>
  </div>
  <div class="form-check">
    <input class="form-check-input" type="checkbox" name="options" value="option2" id="option2">
    <label class="form-check-label" for="option2">
      Option 2
    </label>
  </div>
  <div class="form-check mb-3">
    <input class="form-check-input" type="checkbox" name="options" value="option3" id="option3">
    <label class="form-check-label" for="option3">
      Option 3
    </label>
  </div>
  <div class="text-danger" id="checkbox-error"></div>
  <button class="btn btn-primary">Submit</button>
</form>
Web API Cookbook
Joe Attardi