Michelle Michelle - 1 month ago 13
HTML Question

jquery - select all checkboxes under tbody not working

I'm not sure why this jquery is not working. What I want is pretty straightforward: selecting all check boxes under the region. Could someone help tell why it's not working? Thanks a lot!



$(function(){
$('.select_all').change(function() {
var checkthis = $(this);
var checkboxes = $(this).next('tbody').find('.region_ct');
if(checkthis.is(':checked')) {
checkboxes.attr('checked', true);
} else {
checkboxes.attr('checked', false); }
});
});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table">
<tr>
<th colspan=2>Americas</th>
</tr>
<tr>
<td colspan=2><input type="checkbox" name="region_am_all" class="select_all" value="X" /> Select All</td>
</tr>
<tbody>
<tr>
<td><input type="checkbox" class="region_ct" value="X" /> Argentina</td>
<td class="center"></td>
</tr>
<tr>
<td><input type="checkbox" class="region_ct" value="X" /> Barbados</td>
<td class="center"></td>
</tr>
</tbody>
<tr>
<th colspan=2>Asia</th>
</tr>
...
</table>




Answer

There are a couple of issues there:

  1. I would strongly recommend against intermixing tr and tbody elements. If you're going to use tbody (and you should), use it consistently. Browsers may relocate tr elements into generated tbody elements.

  2. The element you're calling next on doesn't have a following sibling (at all, much less the one you're looking for). You have to traverse up the hierarchy to the tr (if you don't fix #1) or the tbody (if you do).

  3. You don't use attr to set checked, you use prop; and you can use your existing checked boolean rather than if/else, giving is simply checkboxes.prop("checked", this.checked);

Example with updated tbodys, and I've added some countries in the Asia area to demonstrate that only the relevant checkboxes are checked:

$(function() {
  $('.select_all').change(function() {
    var checkthis = $(this);
    var checkboxes = $(this).closest('tbody').next().find('.region_ct');
    checkboxes.prop("checked", this.checked);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table">
  <tbody>
    <tr>
      <th colspan=2>Americas</th>
    </tr>

    <tr>
      <td colspan=2>
        <input type="checkbox" name="region_am_all" class="select_all" value="X" />Select All</td>
    </tr>
  </tbody>

  <tbody>
    <tr>
      <td>
        <input type="checkbox" class="region_ct" value="X" />Argentina</td>
      <td class="center"></td>
    </tr>

    <tr>
      <td>
        <input type="checkbox" class="region_ct" value="X" />Barbados</td>
      <td class="center"></td>
    </tr>
  </tbody>

  <tbody>
    <tr>
      <th colspan=2>Asia</th>
    </tr>
    <tr>
      <td colspan=2>
        <input type="checkbox" name="region_am_all" class="select_all" value="X" />Select All</td>
    </tr>
  </tbody>

  <tbody>
    <tr>
      <td>
        <input type="checkbox" class="region_ct" value="X" />China</td>
      <td class="center"></td>
    </tr>

    <tr>
      <td>
        <input type="checkbox" class="region_ct" value="X" />Vietnam</td>
      <td class="center"></td>
    </tr>
  </tbody>
</table>

You might also consider putting the select_all inside the same tbody with the checkboxes, so you could do away with next.