TheWebs
TheWebs

Reputation: 12923

Selecting multiple checkboxes in Jquery

Consider the following:

$('#num-locations input[type="checkbox"]').on('click', function(e) {
  if (e.target.checked) {
    var location = e.target.dataset.location;

    $('.manage-wrapper').each(function() {
      var city = $(this).data('city');
      if (city !== location) {
        $(this).toggleClass('hide-on-location');
      }
    });
  } else {
    $('.hide-on-location').toggleClass('hide-on-location');
  }
});

So with in this selector: #num-locations input[type="checkbox"] I check if the value is checked, if so I apply a class to any .manage-wrapper that doesn't match the data- attribute.

When you uncheck said checkbox, it removes the class. Great.

This works for one checkbox with in the #num-locations input[type="checkbox"] How ever, I have multiple check boxes with in #num-locations and I cannot target them individually because they are added dynamically.

Question:

How do I write this such that if you check 1 or more checkboxes that it will toggle the class and if you uncheck one or more it untoggles the class?

Example data, all elements that don't match a data-location of Sample would be hidden, great. Uncheck, Sample is now shown.

Now what about checking Sample and Crab Apple, any element that doesn't match Sample or Crab Apple needs to be hidden, when I uncheck Crab Apple, all elements that match Crab Apple should be shown but all elements that don't match Sample Should still be hidden.

I cannot check for specific attributes, because this is dynamic.

Upvotes: 0

Views: 73

Answers (1)

Tyler Roper
Tyler Roper

Reputation: 21672

It sounds like you're trying to create a generic set of filtering checkboxes. If so, the code below should help you out. I mocked up the HTML as you hadn't included it in your question, however I think it should be adequate.

Here are some of the methods used.

  • .map() to change our collection of elements into a collection of their data-city values

  • .get() to return the data values as an Array

  • .filter() to narrow down our manage-wrapper selection to only those not checked

I've also included comments in the code itself to document each step in a bit more detail.

$("#num-locations input[type=checkbox]").on("click", refreshFilters);

function refreshFilters() {
  var $checkedInputs = $("#num-locations input[type=checkbox]:checked");
  var $manageWrappers = $(".manage-wrapper");
  
  $manageWrappers.removeClass("hide-on-location");  //Start with all shown
  if (!$checkedInputs.length) return;               //If nothing is checked, exit early

  //Get the checked cities as an array, e.g. ["New York", "Chicago"]
  var cities = $checkedInputs.map(function() { return $(this).data("city") }).get();
  
  //Find any .manage-wrapper whose data-location is NOT in that array, and hide it
  $manageWrappers
    .filter(function() { return !cities.includes($(this).data("location")); })
    .addClass("hide-on-location");
}
  
.hide-on-location { display: none; }
#num-locations { margin-bottom: 10px; }
.manage-wrapper { border: 1px solid #ccc; padding: 10px; margin: 5px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="num-locations">
  <input type="checkbox" id="cb1" data-city="New York"> <label for="cb1">New York</label>
  <input type="checkbox" id="cb2" data-city="Seattle">  <label for="cb2">Seattle</label>
  <input type="checkbox" id="cb3" data-city="Chicago">  <label for="cb3">Chicago</label>
</div>

<div class="manage-wrapper" data-location="New York">New York</div>
<div class="manage-wrapper" data-location="Seattle">Seattle</div>
<div class="manage-wrapper" data-location="New York">New York</div>
<div class="manage-wrapper" data-location="Chicago">Chicago</div>
<div class="manage-wrapper" data-location="New York">New York</div>
<div class="manage-wrapper" data-location="Chicago">Chicago</div>
<div class="manage-wrapper" data-location="Seattle">Seattle</div>

Upvotes: 1

Related Questions