php – How can I make a posts category filter with checkboxes?-ThrowExceptions

Exception or error:

On my blog archive page, I’m trying to make a category filter with checkboxes so visitors can filter posts by categories without reloading the page.
But I get stuck how to hide items with categories that are not checked.

I wrote a piece of code but don’t really know how to go further from there.

$('.category-filter input[type="checkbox"]').click(function() {
  if ($(this).is(":checked")) {
    var categoryName = $(this).attr("name");

    if ($("article").hasClass('category' + categoryName)) {}
    $(this).toggle;
  } else if ($(this).is(":not(:checked)")) {

  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<aside class="category-filter">
  <label class="filter-category"><input type="checkbox" value="7" name="block" class=" js-filter-checkbox" id="7">Block</label>
  <label class="filter-category"><input type="checkbox" value="16" name="classic" class=" js-filter-checkbox" id="16">Classic</label>
  <label class="filter-category"><input type="checkbox" value="22" name="edge-case-2" class=" js-filter-checkbox" id="22">Edge Case</label>
</aside>

<main>
  <article id="post-2131" class="post-2131 post type-post status-publish format-standard has-post-thumbnail sticky hentry category-geen-onderdeel-van-een-categorie"></article>
  <article id="post-1241" class="post-1241 post type-post status-publish format-standard sticky hentry category-classic category-uncategorized tag-sticky-2 tag-template"></article>
  <article id="post-1938" class="post-1938 post type-post status-publish format-standard hentry category-block"></article>
</main>

I want to hide the articles who don’t have any of the classes that are checked.

How to solve:

I can think of two options to solve this problem. The first one is to use AJAX to reload the list of results when the filter changes.

The second option (which looks like the one you’re trying) is to add the categories of each post in a data-attribute to the element (comma separated), and when the filter changes, loop over each post element and check if the category is present, then hide or show each post element.

The choice between these two options depends on the amount of items you show and if you use pagination. The second option is the most easy one, but it gets you in trouble when you use pagination, because not all posts are loaded at once.

Answer:

$('.category-filter').on('change', function(){
    $('main article').hide();
  $.each($('.category-filter input[type="checkbox"]'), function(el){
    if ($(this).is(":checked")) {
            var categoryName = $(this).attr("name");
      $("article.category-"+categoryName).show();
    }
  });
});

Answer:

This would need to be done with AJAX. There will be a few steps to create this AJAX filter.

Firstly, if you want to only be able to click on checkbox at a time, you need to ensure you all have the same name attribute value. So instead of, name=”block” or name=”classic”, you should call them both, for instance, name=”category-checkbox”.

In your functions.php file, you need to enqueue the following:

function scripts() {
     wp_localize_script ('scripts', 'js_variables', array ('js_home_url' => 
     home_url(), 'ajaxURL' => admin_url( 'admin-ajax.php' ), ''));
}
add_action( 'wp_enqueue_scripts', 'scripts' );

In your javascript file, you need to collect the data from the checkbox. You can do this with the following:

$('.filter-category').change(function() {
  var catId = ($(this).val());
  aJaxFilter(catId);
});

function aJaxFilter(formData) {
  $.ajax({
    url: js_variables.ajaxURL,
    type:'GET',
    data: {
      'formData' : formData,
      'action' : 'listFilteredProducts'
    },
    success:function(data){
      $('main').html(data);
    }
  });
}

You then need to make another file, I call mine ajax-function.php, and I put this in my snippets folder. In there, put the following code:

add_action('wp_ajax_listFilteredProducts', 'listFilteredProducts');
add_action('wp_ajax_nopriv_listFilteredProducts', 'listFilteredProducts');

function listFilteredProducts($wp_query) {
  if(isset($_GET['formData'])) {
    $cat_id = $_GET['formData'];
  }
  $args = array(
  'post_type' => 'post',
  'posts_per_page' => -1,
  'cat' => $cat_id,
  );
  $multiple = get_posts($args);
  foreach($multiple as $single) {
  $ID = $single->ID;
   // Put the code for how you want your article cards to look here.
  }
  wp_die();
}

Leave a Reply

Your email address will not be published. Required fields are marked *