Showing/hiding divs based on checkbox using jQuery

2019-07-19 15:36发布

I have a form with a checkbox (contained within a label #contact). For the change action of this checkbox, I am showing/hiding a div (#options).

To ensure that if the checkbox is checked the #options div always is always shown (and avoid the situation where checking the checkbox actually hides the subjequent options), I am using this code:

$('#contact :checkbox').is(':checked') ? $("#options").show() : $("#options").hide();

This works fine. The problem I have is that instead of a single checkbox with an ID, I want to have multiple checkboxes. I want to show/hide the next instance of my .hidden class based on whether the previous checkbox (within a label with the class .trigger) is checked or not. I have tried this:

$(document).ready(function() {
    if( $('.trigger :checkbox').is(':checked') ) {
        $(this).parent().nextAll('ul.hidden').show();
    } else {
        $(this).parent().nextAll('ul.hidden').hide();
    }
});

But to no avail. The checkboxes are in an unordered list, like this:

<ul>
  <li><label class="trigger"><input type="checkbox" name="02" /> Trigger 1</label>
      <ul class="hidden">
        <li><label><input type="checkbox" name="02-sub1" /> Normal</label></li>
        <li><label><input type="checkbox" name="02-sub2" /> Normal</label></li>
      </ul>
  </li>
  <li><label><input type="checkbox" name="02" /> Normal</label></li>
  <li><label><input type="checkbox" name="03" /> Normal</label></li>
  <li><label class="trigger"><input type="checkbox" name="04" /> Trigger 2</label>
      <ul class="hidden">
        <li><label><input type="checkbox" name="04-sub1" /> Normal</label></li>
        <li><label><input type="checkbox" name="04-sub2" /> Normal</label></li>
      </ul>
  </li>
</ul>

I can't see where I'm going wrong here; presumably my selector is incorrect, but I've played around with the syntax for ages and not got anywhere. Thanks in advance (and thank you for reading this far).

2条回答
干净又极端
2楼-- · 2019-07-19 15:58

You need to run your code inside a change handler, so this refers to the checkbox you want, like this:

$(document).ready(function() {
   $('.trigger :checkbox').change(function() {
     if( $(this).is(':checked') ) {
       $(this).parent().nextAll('ul.hidden').show();
     } else {
       $(this).parent().nextAll('ul.hidden').hide();
     }
   });
});

...and that can be made much shorter with .toggle(bool), like this:

$(function() {
   $('.trigger :checkbox').change(function() {
     $(this).parent().nextAll('ul.hidden').toggle(this.checked);
   });
});

If you need it to run when the page loads, so the show/hide states match the checkbox, just call that change handler with .change() (shortcut for .trigger('change')), like this:

$(function() {
   $('.trigger :checkbox').change(function() {
     $(this).parent().nextAll('ul.hidden').toggle(this.checked);
   }).change();
});
查看更多
爷、活的狠高调
3楼-- · 2019-07-19 16:01

You know you can roll your own fields, right? The typical way to do that is with a "rel=" field that has no meaning in HTML but can be picked up and used in jquery.

if ($('#contact :checkbox').is(':checked')) {
    $("#" + $('#contact :checkbox').attr('rel')).show();
} else {
    $("#" + $('#contact :checkbox').attr('rel')).hide();
}

And then:

  <li><label class="trigger"><input type="checkbox" name="04" rel="hidden-04" /> Trigger 2</label>
      <ul class="hidden" id="hidden-04">
        <li><label><input type="checkbox" name="04-sub1" /> Normal</label></li>
        <li><label><input type="checkbox" name="04-sub2" /> Normal</label></li>
      </ul>
  </li>

So then, when the checkbox named 04 is checked, we look in its rel field for the id of the object to hide() or show(). I think that's a LOT easier than trying to walk the dom to find the target object.

查看更多
登录 后发表回答