Shumaise Mohammed
Shumaise Mohammed

Reputation: 417

Nested table checkbox check/Uncheck

I have a page with nested table and checkbox for checking all the table cell <td>. And checkbox for each table cell <td> for checking respective cell.

What I'm trying to do is

  1. CheckAll checkbox checks/uncheck all the parent and child checkbox
  2. Uncheck a parent checkbox unchecks CheckALL checkbox and unchecks all the child checkbox
  3. Check a parent checkbox checks all child checkbox and finds out if all other parent checkbox are checked or not, to check CheckALL checkbox
  4. checking a child checkbox should check the respective parent
  5. unchecking a child checkbox should check if siblings are checked, if not checked parent checbox should get unchecked and if checkALL checkbox is checked it should get unchecked too.

I'm unable to do this.

Here is what I have tried.

html:

<table class="table table-striped tablesorter">
  <thead>
    <tr colspan="2">
      <th>
        <input type="checkbox" id="checkedAll">
      </th>
      <th>Check/UnCheck ALL Boxes</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <input type="checkbox" class="checkParent">
      </td>
      <td>1KWT</td>

    </tr>
    <tr>
      <td colspan="2" style="padding: 0">
        <table class="innertable" style="margin: 10px 0px 10px 50px;border: 1px solid #d0d0d0">
          <thead>
            <tr>
              <th></th>
              <th>Sub</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>
                <input type="checkbox" class="checkChild" style="margin-top: -3px"> </td>
              <td>1KWT1</td>
            </tr>
            <tr>
              <td>
                <input type="checkbox" class="checkChild" style="margin-top: -3px"> </td>
              <td>1KWT2</td>
            </tr>
          </tbody>
        </table>
      </td>
    </tr>
    <tr>
      <td>
        <input type="checkbox" class="checkParent" style="margin-top: -3px"> </td>
      <td>1OMN</td>
    </tr>
    <tr>
      <td colspan="2" style="padding: 0">
        <table class="innertable" style="margin: 10px 0px 10px 50px;border: 1px solid #d0d0d0">
          <thead>
            <tr>
            <th></th>
              <th>Sub</th>
             </tr>
          </thead>
          <tbody>
            <tr>
              <td>
                <input type="checkbox" class="checkChild" style="margin-top: -3px"> </td>
              <td>1OMN1</td>
            </tr>
            <tr>
              <td>
                <input type="checkbox" class="checkChild" style="margin-top: -3px"> </td>
              <td>1OMN2</td>
             </tr>
          </tbody>
        </table>
      </td>
    </tr>
  </tbody>
</table>

script:

$(document).ready(function() {

  $("#checkedAll").change(function(){
    if(this.checked){
      $(".checkParent, .checkChild").each(function(){
        this.checked=true;
      });              
    }else{
      $(".checkParent, .checkChild").each(function(){
        this.checked=false;
      });              
    }
  });

  $(".checkParent").click(function () {
    if ($(this).is(":checked")){
      var isAllChecked = 0;
      $(".checkParent").each(function(){
        if(!this.checked)
           isAllChecked = 1;
      }) 
      $(".checkChild").prop("checked", true);
      if(isAllChecked == 0){ $("#checkedAll").prop("checked", true); }     
    }else {
      $("#checkedAll, .checkChild").prop("checked", false);

    }
  });

  $(".checkChild").click(function () {
    if ($(this).is(":checked")){
    $(".checkParent").prop("checked", true);

    }else {
      $(".checkParent").prop("checked", false);

    }
  });


});

link to fiddle https://jsfiddle.net/4zhhpwva/

Upvotes: 3

Views: 1801

Answers (2)

Shumaise Mohammed
Shumaise Mohammed

Reputation: 417

I've done it. Improvement's are welcomed. Here is the updated script

$(document).ready(function() {

  $("#checkedAll").change(function() {
    if (this.checked) {
      $(".checkParent, .checkChild").each(function() {
        this.checked = true;
      });
    } else {
      $(".checkParent, .checkChild").each(function() {
        this.checked = false;
      });
    }
  });

  $(".checkParent").click(function() {
    if ($(this).is(":checked")) {
      var isAllChecked = 0;
      $(".checkParent").each(function() {
        if (!this.checked)
          isAllChecked = 1;
      })
      $(this).closest("tr").next("tr").find(".checkChild").prop("checked", true);
      if (isAllChecked == 0) {
        $("#checkedAll").prop("checked", true);
      }
    } else {
      $("#checkedAll").prop("checked", false);
      $(this).closest("tr").next("tr").find(".checkChild").prop("checked", false);
    }
  });

  $(".checkChild").click(function() {
    if ($(this).is(":checked")) {

      var isChildChecked = 0;
      $(".checkChild").each(function() {
        if (!this.checked)
          isChildChecked = 1;
      });
      if (isChildChecked == 0) {
        $("#checkedAll").prop("checked", true);
      }
      $(this).closest("table").closest("tr").prev("tr").find(".checkParent").prop("checked", true);

    } else {
      var isAllSiblingChecked = 0;
      $(this).closest("tr").nextAll("tr").find(".checkChild").each(function() {
        if ($(this).is(":checked"))
          isAllSiblingChecked = 1;
      });

      $(this).closest("tr").prev("tr").find(".checkChild").each(function() {
        if ($(this).is(":checked"))
          isAllSiblingChecked = 1;
      });

      if (isAllSiblingChecked == 0) {
        $(this).closest("table").closest("tr").prev("tr").find(".checkParent").prop("checked", false);
      }
      $("#checkedAll").prop("checked", false);
    }
  });

});

I've updated the fiddle here to see the working https://jsfiddle.net/shumaise/4zhhpwva/10/

Upvotes: 3

Rose Robertson
Rose Robertson

Reputation: 1256

Your issue is that the selectors you have in place are always getting ALL checkchildren and ALL checkParents instead of just the nested ones. You need to make it more specific.

There's definitely a better way to do this, but as an example to show what I mean, on the checkParent click function, instead of $(".checkChild") which will grab all checkChildren on the page, you probably want to do something like $(this).closest("tr").next("tr").find(".checkChild")

That said, if you change your markup so that they are nested under a common ancestor that isn't shared with any other checkChild elements, that could be simplified so that the .next wouldn't be needed.

I've updated your fiddle here - https://jsfiddle.net/4zhhpwva/3/ so you can see it working...

Upvotes: 2

Related Questions