Filter WordPress posts by multiple taxonomy terms with AJAX

UPDATE: 14. Nov. 2016
Demo is now extended to show standard numbered pagination or infinite scroll.

This is the second part of the post where I show how to display and filter WordPress posts based on taxonomy term.
In this post I will create a working script which shows how to filter posts by multiple terms.

I will include the entire code but I will not explain in depth what’s going on there because I already did that in previous post.
If you missed the first part please check here How to filter WordPress posts by custom taxonomy term with AJAX and pagination.

Explanation

The idea is very simple, in the previous post you can find out how to:

  1. Display list of terms
  2. Get taxonomy and term of clicked element
  3. Get and display posts by selected term

This post will just extend this feature so instead only one element, we will get all active terms and retrieve posts for all active terms.
To do that we would just need to slightly modify our javascript to:

What does this do?

  1. On click toggle parent li item class ‘active’
  2. Get all .active li items
  3. Get ‘taxonomy’ and ‘term’ slug from all elements: $terms[taxonomy_name] = ['term1', 'term2'];
  4. Pass params to our function that gets posts by selected terms

Function which gets posts by AJAX stays the same like in previous posts.

PHP function

After we get all params with jQuery we need to get posts by selected terms. To do that we need to modify our PHP function, and use ‘tax_query’ in our WP_Query.
Snippet from function:

What does this do?

Basically script stays the same like in previous post, the only difference is that we now pass data as an array of 'taxonomy' => array_of_terms[]' and we need to loop trough this array and construct ‘tax_query’.

Working demo example with pagination
Working demo example with infinite scroll

Downloads

  1. PHP file Gist
  2. Javascript file Gist

28 Comments

    1. Hi Rubic,

      Thanks for reporting, I have fixed the issue.
      Problem was that I forgot to include ‘wp_ajax_nopriv’ so it was not working for logged out users.

      Cheers.

  1. Hi, thank you for tutorial, when i first try your demo, its doesn’t work, but now its fixed for logged out users :)
    I wonder how to show all posts when:
    – User visit page with all posts (blog in my case) for the first time
    – User first select some terms, and after that un-select everything (return to default state)
    Also what do you think about using/adding hidden term list item, that will contain default wordpress category?
    I mean: my default wp category is Uncategorized(for testing this) and i have cat 1 to 12 as children of uncategorized
    When i make hidden list item li.uncategorized .active
    it should load all posts by default, whnever i click on other item it should remove active class from li.uncategorized .active, so my sorting should work??
    Currently i’m using barba.js pjax, so my testing website feels like its fully ajaxified, i read somwhere that pjax is better for seo than ajax, its doesn’t hide content for search engines
    But if we could load all posts by default, or load all posts when any terms aren’t selected it still should be fine for seo, yes?

  2. Hi Gabrielle,

    I’ve updated example to include ‘Show all’ which is selected by default.
    Hope this clears all your questions.

  3. Hi Vlado,

    Wonderful guide, works perfectly for me!

    Next step for me is to create infinite-scroll / load more pagination instead of page numbering to make it all ajaxified :).

    Anyone that has managed to do this?

  4. Would be amazing, I don’t think it should be a huge deal while you’re already using a sort of ajax-pagination: I just think the load more option is nicer than replacing a number of posts with new posts (page numbers).

    Meanwhile I will try to expand the filtering of posts by adding filters from meta data in select inputs. Cause im using your function with custom taxonomies to filter apartments by “Place”. Now i need to add “No of rooms” and “Min/Max-price” in select dropdowns. I guess by adding some kind of meta_query key->rooms type of thing.

    See: https://postimg.org/image/4q1llo7td/

    1. Hi,
      Article is now updated to work either with infinite scroll or numbered pagination.
      Please check the demo with infinite scroll here and update your code accordingly.
      I’m not sure are you using shortcode or not, but to use infinite scroll you would need to add param pager=”infscr”, that would display ‘Load more’ button instead of numbered pagination.

  5. Hi Vlado,

    I’m also intarasted in this infinite-scroll option.

    Could you help me with query for time.
    I would like to user can filter by X h ago for example …

    Thanks Nikola

    1. Article is now updated to work either with infinite scroll or numbered pagination.
      Please check the demo with infinite scroll here and update your code accordingly.
      I’m not sure are you using shortcode or not, but to use infinite scroll you would need to add param pager=”infscr”, that would display ‘Load more’ button instead of numbered pagination.

      Regarding the time query, please consult WP_Query documentation on codex, the best way is to trial and error until you get desired results on your localhost.

  6. Hi Vlado,

    could you please check your files on github.
    I really tried all but there are some differences between codes on post / github and your working code :) .

    First of all in any file i cannot find this piece of code for example:

    <a href="#" data-filter="taxonomy; ?>” data-term=”all-terms” data-page=”1″>
    Show All

    so i need to search inside post to see what changes you have made and that is not problem,
    problem is that doesn’t work after that for example on infinity scroll i get infinity scroll and i get paging, when i click load more it reload second page with posts, and if i use pager=”infscr” it just show me pagination :)

    If you can make resume with final files which you use on your site it would be very nice!

    I will really appreciate your help and thanks once again for this great tutorial!

    Cheers!

  7. Hey Vlado Bosnjak,

    I am using tag with options for the filter selection. How can i make your code work with my markup?

    $(‘.sc-ajax-filter-multi’).on(‘click’, ‘a[data-filter], .pagination a’, function(event) {}

    I have tried replacing a[data-filter] with option[data-filter]..it doesn’t work. Console log returns nothing

    Please help!

    1. Hi Dylan,

      Sorry but I’m not sure I understand whats wrong.
      If you are using select, then you probably should do:

      $('select').change( function() { ... })
      

      To get the selected option

  8. Great tutorial, I learned a bunch here that directly applies to the project I’m putting together. Thank you!

    I have a question about setting the specific terms to be used with // ‘terms’ => false, // Get specific taxonomy terms only

    Is it best practice to use the term_id? I suppose it would be because if you changed the name then the id would still be maintained? If desired, would it be easy enough to change the list of terms to names or slugs?

    thanks again.
    cheers

    1. Hi Stephen,

      Yes, I think by ID would be best.
      You can get entire term object and then display what you like.

  9. great ! I love this tutorial and codes.but could you please tell me how to show category name instead of category slug in the selection confirmation msg section? thank you very much

    1. Hi Eric,

      I’m not sure where exactly is this code, but if $trm = slug of the term, you can get term data with get_term_by function. Anyhow, you can do print_r and see what is $term.

  10. Hy Vlado,

    awesome posts – it pushes my concept in the right direction! But what if i have to filter in multiple taxonomies. In my case i have to filter a recipe database (http://www.genussfreude.at/rezepte/). One of the taxonomies is “season”, another is “ingredients”. I have to combine them in a way like in this example (https://www.loveandlemons.com/recipe-browser/#all). Do you have a idea how to achieve that?

    Thanks for your reply and kind regards,
    Bernhard

    1. Hi Bernhard,

      Basically it’s the same thing. Just instead of 1 tax add array.
      In the shortcode part here L8: https://www.bobz.co/filter-wordpress-posts-by-custom-taxonomy-term-with-ajax-and-pagination/

      $a = shortcode_atts( array(
              'tax'      => ['tax_1', 'tax_2], // Taxonomy
              'terms'    => false, // Get specific taxonomy terms only
              'active'   => false, // Set active term by ID
              'per_page' => 12 // How many posts per page,
              'pager'    => 'pager' // 'pager' to use numbered pagination || 'infscr' to use infinite scroll
      ), $atts );

      Then, on L16, you don’t do get_terms($a['tax']);, but instead you do:

      foreach ($a[tax] as $tax) {
         get_terms($tax);
         ... the rest of code ...
      }

      That’s roughly, but in short you just need to convert my code for one taxonomy into for/foreach loop.
      On click of each term, you mark him active and when making request get all with class ‘active’ and read tax/term_id from them, and construct WP_Query out of it.

      BR
      Vlado

  11. This is a life-saver!!! I have more complex taxonomy terms, but at least this gets me started! I was never able to figure this out on my own and now I can ajaxify ALL the things! Thank you so much!!

Leave a Reply

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