Skip to content
Advertisement

Check and Uncheck Parent/Child Checkboxes using Jquery

I have to use group of checkboxes in my project.

This is how my HTML look like:

<table id="myTable">
<tr>
  <td>
    <label>
      <input type="checkbox" class="parent" name="mod[6]" value="1">
    </label>
  </td>
  <td><span>Parent Module</span></td>
  <td>
    <label>
      <input type="checkbox" name="mod[7]" value="1"> Sub Module
    </label>
    <label>
      <input type="checkbox" name="mod[8]" value="1"> Sub Module
    </label>
    <label>
      <input type="checkbox" name="mod[9]" value="1"> Sub Module
    </label>
  </td>
</tr>
<tr>.....</tr>
<tr>.....</tr>
</table>

Using this checkboxes, users can select their preferred parent and sub module selection. When making that selection, it should work as follows.

  • When a parent is checked, all children are checked under it. (Parents and children are separated by a row on the table)
  • When a parent is unchecked, all children are unchecked under it.
  • At the very least, When one child is checked, its parent should be checked.
  • When no child is checked, its parents should not be checked.

I have done this work to some extent. But I look forward to your help in completing this.

This is how I tried it using Jquery.

$('#myTable').on( "change", "label > input[type=checkbox]", function(e) {
  var checkboxes = $(this).closest('tr').find("input[type=checkbox]");
  if ($(this).hasClass("parent")) { 
    if ($(this).prop("checked")) {
      checkboxes.prop("checked", true);
    }
  }
});

Advertisement

Answer

Update

Added a “Check All” box in the <thead> Added the third state called indeterminate which is applied to a .parent or #all when some of their subordinate checkboxes are checked.

Assigned .child class to the subordinate checkboxes just to make it a little easier to follow hopefully. Details are commented in the example.

// *️⃣ Code for indeterminate state - There are comments for removal
// Bind all checkboxes to the change event
$(':checkbox').on('change', checkUncheck);

function checkUncheck(e) {
  // The tag the user checked/unchecked
  const $this = $(this);
  // Reference to the closest <tr>
  const $row = $this.closest('tr');
  /*
  If the user clicked a .parent...
  ...and if it is checked...
  ... .find() all the <td> of $row...
  ...and check them all...
  ...otherwise uncheck them all
  */
  if ($this.is('.parent')) {
    if ($this.is(':checked')) {
      $row.find('.child').prop('checked', true);
    } else {
      $row.find('.child').prop('checked', false);
    }
  }
  /*
  If the user checked/unchecked a .child...
  ... .makeArray() of all of $row .child and...
  ... if .every() <td> is .checked then check .parent
  ... and if .some() <td> are .checked then .parent is...
  ... indeterminate, otherwise uncheck .parent
  */
  if ($this.is('.child')) {
    $row.find('.parent').prop('indeterminate', false);  //*️⃣
    const chxArray = jQuery.makeArray($row.find('.child'));
    let rowChecked = chxArray.every(cb => cb.checked);  //*️⃣
    let someChecked = chxArray.some(cb => cb.checked);
    if (rowChecked) {    /* if (someChecked) { */       //*️⃣ 
      $row.find('.parent').prop('checked', true);
    } else if (someChecked) {
      $row.find('.parent').prop('indeterminate', true); //*️⃣
    } else {
      $row.find('.parent').prop('checked', false);
    }
  }
  /*
  If the user clicked #all...
  ...and if it is checked...
  ... .find() all the <td> of $tB...
  ...and check them all...
  ...otherwise uncheck them all
  */
  if ($this.is('#all')) {
      $('.parent').prop('indeterminate', false); //*️⃣
    if ($this.is(':checked')) {
      $(':checkbox').prop('checked', true);
    } else {
      $(':checkbox').prop('checked', false);
    }
  }
  /*
  If the user checked/unchecked a .child or .parent...
  ... .makeArray() of all of <td> in <tbody> and...
  ... if .every() <td> is checked...
  ... #all is checked and if .some() <td> are checked...
  ... then #all is indeterminate...
  ... otherwise uncheck #all
  */
  let allArray = jQuery.makeArray($(':checkbox').not('#all'));
  if (allArray.every(cb => cb.checked)) { 
    $('#all').prop('indeterminate', false); //*️⃣
    $('#all').prop('checked', true); /* Move to: ✳️ */
  } else if (allArray.some(cb => cb.checked)) {
    $('#all').prop('indeterminate', true);  //*️⃣ ✳️
  } else {
    $('#all').prop('indeterminate', false); //*️⃣
    $('#all').prop('checked', false);
  }
}
<table><thead><tr><th><label><input type=checkbox id=all></label><th>All Modules<th><tbody><tr><td><label><input type=checkbox class=parent name=mod[6] value=1></label><td><span>Parent Module</span><td><label><input type=checkbox class=child name=mod[7] value=1> Sub Module</label> <label><input type=checkbox class=child name=mod[8] value=1> Sub Module</label> <label><input type=checkbox class=child name=mod[9] value=1> Sub Module</label><tr><td><label><input type=checkbox class=parent name=mod[6] value=1></label><td><span>Parent Module</span><td><label><input type=checkbox class=child name=mod[7] value=1> Sub Module</label> <label><input type=checkbox class=child name=mod[8] value=1> Sub Module</label> <label><input type=checkbox class=child name=mod[9] value=1> Sub Module</label><tr><td><label><input type=checkbox class=parent name=mod[6] value=1></label><td><span>Parent Module</span><td><label><input type=checkbox class=child name=mod[7] value=1> Sub Module</label> <label><input type=checkbox class=child name=mod[8] value=1> Sub Module</label> <label><input type=checkbox class=child name=mod[9] value=1> Sub Module</label></table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement