3 Steps to Create AJAX Post Filters
So many people asks me about post filters. So I decided to write a simple post about it — so everyone could understand how it works. 
In this post I will show you how to create an asynchronous AJAX filter by yourself, which allows to filter posts by taxonomy terms, meta values and sort results by publish date.
I do not recommend to use plugins for these purposes if possible.
Step 1. Everything begins with a HTML form
Our filter form will consist of 4 parts. I’ll describe each part of the form separately.
1.1 Filter posts by a category or by taxonomy terms
First part of the form is a dropdown <select>
of taxonomies. To create that <select>
you can freely use get_terms()
function. This function works not only for custom taxonomies but for default categories and tags as well.
if( $terms = get_terms( array( 'taxonomy' => 'category', // to make it simple I use default categories 'orderby' => 'name' ) ) ) : // if categories exist, display the dropdown echo '<select name="categoryfilter"><option value="">Select category...</option>'; foreach ( $terms as $term ) : echo '<option value="' . $term->term_id . '">' . $term->name . '</option>'; // ID of the category as an option value endforeach; echo '</select>'; endif;
You can replace the taxonomy
parameter value on line 2 with any custom taxonomy name or post_tag
.
By the way, it is also possible to combine this code with my multisite plugin, you get it here and network_get_terms() function. So, all network categories will be in the select dropdown and all the network posts will be displayed as the filter search results.
1.2 Filter posts by custom field values as well
I use range of prices. In our case price is a custom field value that is stored in wp_postmeta
table under the _price
key in database.
<input type="text" name="price_min" placeholder="Min price" /> <input type="text" name="price_max" placeholder="Max price" />
I will show you how to create a meta_query
filter in step 3 of this tutorial but you can also read more about meta_query
usage here.
1.3 Ascending or Descending Order
Simple radio buttons will help us to sort posts in ascending or descending order.
<label> <input type="radio" name="date" value="ASC" /> Date: Ascending </label> <label> <input type="radio" name="date" value="DESC" selected="selected" /> Date: Descending </label>
For simpleness I decided to sort posts by date only, but you can easily sort posts by name alphabetically or by custom fields values.
1.4 Checkbox filter – Display posts with featured images only
Actually the featured image is just an attachment ID that is stored like a custom field value under _thumbnail_id
key. We will just check if it exists.
<label> <input type="checkbox" name="featured_image" /> Only posts with featured images </label>
You can also add a search field just like a simple <input type="text" />
and in Step 3 use s=
parameter of WP_Query
. Easy-peasy ?
Complete form code
You can skip all the previous field descriptions and use the code below as is. Insert it anywhere you want the filter to be.
<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter"> <?php if( $terms = get_terms( array( 'taxonomy' => 'category', 'orderby' => 'name' ) ) ) : echo '<select name="categoryfilter"><option value="">Select category...</option>'; foreach ( $terms as $term ) : echo '<option value="' . $term->term_id . '">' . $term->name . '</option>'; // ID of the category as the value of an option endforeach; echo '</select>'; endif; ?> <input type="text" name="price_min" placeholder="Min price" /> <input type="text" name="price_max" placeholder="Max price" /> <label> <input type="radio" name="date" value="ASC" /> Date: Ascending </label> <label> <input type="radio" name="date" value="DESC" selected="selected" /> Date: Descending </label> <label> <input type="checkbox" name="featured_image" /> Only posts with featured images </label> <button>Apply filter</button> <input type="hidden" name="action" value="myfilter"> </form> <div id="response"></div>
Some comments:
- Line #1. I use default WordPress function
site_url()
to get an actual website URL - Line #1.
admin-ajax.php
is the default WordPress AJAX processor. I place it into the form action attribute just for simplicity, you can also get it withadmin_url('admin-ajax.php')
. - Line #23. Hidden input field with the
myfilter
attribute is required — this is how WordPress recognize what function to use. - Line #25.
#response
div element is the container where the code will paste the result data.
Step 2. jQuery script to Send a Request and to Receive Result Data
In this part of the tutorial I suppose that you know just a little bit about jQuery, at least how to include it to a website page. Here is the complete jQuery-based processing code. It will send the request when the form is submitted.
jQuery(function($){ $('#filter').submit(function(){ var filter = $('#filter'); $.ajax({ url:filter.attr('action'), data:filter.serialize(), // form data type:filter.attr('method'), // POST beforeSend:function(xhr){ filter.find('button').text('Processing...'); // changing the button label }, success:function(data){ filter.find('button').text('Apply filter'); // changing the button label back $('#response').html(data); // insert data } }); return false; }); });
Step 3. PHP code to Process the Request
I think it is the most interesting part. In this part you decide how to filter the posts the best way. This code is fully based on WP_Query
. But it is also a good idea to do it with query_posts()
.
add_action('wp_ajax_myfilter', 'misha_filter_function'); // wp_ajax_{ACTION HERE} add_action('wp_ajax_nopriv_myfilter', 'misha_filter_function'); function misha_filter_function(){ $args = array( 'orderby' => 'date', // we will sort posts by date 'order' => $_POST['date'] // ASC or DESC ); // for taxonomies / categories if( isset( $_POST['categoryfilter'] ) ) $args['tax_query'] = array( array( 'taxonomy' => 'category', 'field' => 'id', 'terms' => $_POST['categoryfilter'] ) ); // create $args['meta_query'] array if one of the following fields is filled if( isset( $_POST['price_min'] ) && $_POST['price_min'] || isset( $_POST['price_max'] ) && $_POST['price_max'] || isset( $_POST['featured_image'] ) && $_POST['featured_image'] == 'on' ) $args['meta_query'] = array( 'relation'=>'AND' ); // AND means that all conditions of meta_query should be true // if both minimum price and maximum price are specified we will use BETWEEN comparison if( isset( $_POST['price_min'] ) && $_POST['price_min'] && isset( $_POST['price_max'] ) && $_POST['price_max'] ) { $args['meta_query'][] = array( 'key' => '_price', 'value' => array( $_POST['price_min'], $_POST['price_max'] ), 'type' => 'numeric', 'compare' => 'between' ); } else { // if only min price is set if( isset( $_POST['price_min'] ) && $_POST['price_min'] ) $args['meta_query'][] = array( 'key' => '_price', 'value' => $_POST['price_min'], 'type' => 'numeric', 'compare' => '>' ); // if only max price is set if( isset( $_POST['price_max'] ) && $_POST['price_max'] ) $args['meta_query'][] = array( 'key' => '_price', 'value' => $_POST['price_max'], 'type' => 'numeric', 'compare' => '<' ); } // if post thumbnail is set if( isset( $_POST['featured_image'] ) && $_POST['featured_image'] == 'on' ) $args['meta_query'][] = array( 'key' => '_thumbnail_id', 'compare' => 'EXISTS' ); // if you want to use multiple checkboxed, just duplicate the above 5 lines for each checkbox $query = new WP_Query( $args ); if( $query->have_posts() ) : while( $query->have_posts() ): $query->the_post(); echo '<h2>' . $query->post->post_title . '</h2>'; endwhile; wp_reset_postdata(); else : echo 'No posts found'; endif; die(); }
Now you know the basics and you can easily create filters like this in WordPress:

If you still have problems with filters, please leave a comment below.
Comments — 232
Whether this method is effective in a multi network plugin?
Hello,
yes, you can use this method with my Multisite plugin.
good work
thx
Use the wp-navi, I want a page feed.
Could you?
Hi,
yes, you can use wp-navi or the custom function from this tutorial about multisite pagination.
Awesome and helpful article. Thanks, Misha!
Is it possible to display on the same screen?
Of course — that’s how it should work.
the result is displayed id admin-ajax.php and not in the same page.
do you have any idea why?
Please check your JavaScript console (in browser) for errors.
Iv’e checked… on errors.
Any ideas?
If the result is displaying in admin-ajax.php it means only 1 thing – jQuery AJAX code doesn’t work.
Please contact me via email, I will help you.
Good read!
No need for event.preventDefault();?
$(‘#filter’).submit(function(event){
event.preventDefault();
no need, there is
return false
already.Is it possible to display all posts at first then apply a filter to those posts? I’m able to manipulate the WP_Query to display what I need, but only after I hit the “Apply Filter” button.
Thanks in advanced.
Hello Scott,
yes, just display all your posts here:
Very cool. Thanks.
Great write up, works like a charm.
How would add a second select for a second Taxonomy?
Just the same like the first, duplicate the necessary lines from each part of the code but to not forget to change taxonomy name.
Hello! Is it possible to increase the amount of posts that return after we apply the category filter. At the moment it seems to default to 10. Maybe an ajax “load more” button would work?
Hi John,
first option is creating load more button — I can not describe in two words how to do it here — maybe I will publish a post later about that.
Second option is to change default WordPress parameter in «Settings > Reading» from 10 to another value.
And the third option is to force
posts_per_page
parameter in the code in step 3 on line 2 ($args
array).Great pluggin Misha,
I would like to implement pagination or load more button. Pls can you point me out?
Kind Regards Andrija
Hello,
Yes, I recommend you to look at this post.
Thanks for quick replay. I have checked it bit dont know how to combine it with this post and already filtered data. Your tuts about filtering works perfect but cant figure this missing puzzle
You’re not the first who are asking about that, maybe I will write a separate detailed tutorial soon.
But the answer is too long to leave it in comments, sorry. Just check blog updates from time to time.
Hello everyone,
The new post about Filters + Load More is ready. I hope it will be helpful.
Hi Misha,
Thank you for this awesome tutorial. Working like a charm.
I want to show the excerpt. When using get_the_excerpt, it is outputting my shorcode tags.
On my normal pages the excerpt is working like it should, but i can’t get to work with your code.
Can you help me out.
Thanks
Hi, Rob,
thank you :)
Did you try this
$query->post->post_excerpt
?Yes! It is working.
Thank you so much.
Last question:
Is it posible to use this for multiple posttypes?
Do i have to create another hook?
Welcome!
Try to add the
post_type
parameter in the$args
array:Yes ! Thanks :)
I’ve tried this one before, but it’s showing all the posttypes together.
I have 3 pages, each with there own posttypes, so i want to filter within each one and just show the results separately on the pages.
Is this possible?
Ok, I understand,
First, depending on your page, add to the filter HTML the following:
After that in the PHP
$args
param add:Thanks Misha! It worked!
Hi Misha,
Thank you for this awesome tutorial.
I try this code separately with price and date its work well. Now i’m trying to merge it but fail. Can you please help??
Hi Farooq,
the line #3 of your code is wrong. Try to use ‘ASC’ or ‘DESC’ strings instead.
Hi Misha,
I try my best but unable to solve it. In your filter ASC & DESC for date is working,
Now i’m trying ASC & DESC for price custom field also.
Can you please elaborate it??
Best Regards.
Hi,
when you sort by meta values, meta key parameter is also required.
Could you please update this with ability to have pagination and also ‘infinite loading’? I’ll be very thankful!
Hi,
of course I will do it when I have time.
Hi, thanks a lot for making this tutorial! A quick question, in part 3 starting from line 60, is it possible to somehow hook an existing template without re-creating all the code? For instance, I have a custom archive page that already presents the posts exactly how I want them to look. Is it possible to use this archive to show the filtered results? Not sure if I’m explaining this right :)
Hi :)
I this case I usually use a custom function where I pass the $post object.
Hello Misha, nice work, works good! But would it also be possible to disable the apply button, and still filter the items the user has selected?
Hello,
yes, it is possible, but now I’m in the mountains and have only iPhone – so I can not provide you with the code, sorry.
No problem, i’ll wait until you have got the tim,e when you get back. Enjoy your vacation?
Ok, thank you! I will come back on 7th February.
I am wondering how hard is it to get the ajax to run on a change of the select dropdown. I have tried this using
However, the ajax loads on a separate page, and I am not directed to the $(‘#filter’).submit(function(){…}
Otherwise, this is very helpful!
Hi Daniel,
I recommend you to implement it the following way:
The second step is jQuery:
As someone who was struggling with this, I want to mention that I had to make an additional change for this to work:
From this:
To this:
great stuff :)
Thank you :) I will add it to the post.
Great tutorial mate, I’ve got only one problem:
– dropdowna list is showing categories, but ajax response return only data from post_type =>post,
I’ve set the post type to my custom post type – portfolio :
But it’s still not working. Can you please help me?
Hi Maciek,
thanks,
the post_type parameter should never be inside tax_query. Add id to the
$args
array the following way:Awesome stuff :) Cheers! :)
One more question – how to submit form on clicking radio button?
Try to replace this part of the jQuery script:
to this:
Ok thanks :) Last one thing:) Is there a way of showing in list of categories something like ‘All’? So when I click on it it’s gonna show all categories?
Just add to your select dropdown something like:
Dear Misha
Thanks for this amazing tuto
I’ve tried to add this : All categories to show all results
But it doesn’t work, it shows : nothing found.
Do you know why ?
Other thing
I’d like to use the filter twice in the same page cause i have two tab with different posts i’d like to filter by ‘city terms’
But, in the second tab, it doesn’t work with ajax but it works if i click on the button
I’ve tried for hours but i can’t do…
Could you help me
Even if i understand you made a lot
Many thanks
Damien
About all categories – there is somewhere a small mistake in your code, please look.
About two filters. As an option use different IDs in HTML elements, use twice the given jQuery code with the different selectors and AJAX action parameters.
It depends on your situation of course, but PHP code can be the same – in that case AJAX action parameter will be the same.
Hi Misha,
I use this, for my home page, and Anytime the result is “0”…
Can you help me ?
Thank you so mush :3
Hi Beifong,
it means that ajax is ok, but it is not connected to the hook/function. Please read the post one more time and pay attention to the
action
hidden field and hook ( add_action() arguments ) names.Works perfect. I have been using this for many times
How can I trigger some jQuery after ajax is done loading?
Thanks!
You can add in into the
success:function(data){ }
(Step 2).This works for me. Thank you!
Hello, Ali.
I had the same problem with my custom post type category. Probably, you are already find the answer, but maybe some one else will need it
Thank you Tanya for your useful comment :)
this save my day !!!! thx you very much ;)
Hi Misha i tried to used the form but i have some questions, if i used checkboxes, (one checkbox for one taxonomy for example), when i select one check box the result is ok, but when i check two checkboxes (two taxonomies terms) , the resul just show the post that belog to one term??
Hi Javier,
did you use the same name attributes for both checkboxes?
Hi finally i can use the checkbox for two taxonmies (marca and edad) but now my problem is that i want display only post for a especific categories, (i working with woocommerce) my code is:
Where are your specific categories in your code?
I do not like the way how you filter taxonomies, please look, how
meta_query
implemented in the post, and make the same fortax_query
– they are very similar.P.S. Please, use the buttons in editor (php, js etc) when want to insert the code in comment!
Hi Misha, the code only show 5 of 30 results, How can I do to show all the results?
Hi Mark,
try to add
posts_per_page
parameter to your$args
array.Thanks Misha! I was able to do something very similar and it worked perfectly following your tutorial.
If you have an archive of Movies and the user selects 3 filter options (Horror, Comedy, Documentary), how would they be able to send that page with those filters selected? How would you generate a shareable link?
Looking forward to your response!
Thanks,
Jose
Hi Jose,
actually there are two ways – you can use $_GET parameters in URL or a hash.
So,
?post_tp=Horror,Comedy,Documentary
or#post_type=Horror,Comedy,Documentary
.When the filter page is loading, you’re checking the
$_GET['post_tp']
, select the appropriate values in the form and run your custom WP_Query for those parameters.Second way is when you check the parameters in JavaScript
window.location.hash
, after that you select the appropriate values in the form and script send the AJAX request.P.S. I do not recommend to use
post_type
as a $_GET parameter name, because there are could be conflicts.Hi Misha, I really appreciate the code.
Could you please let me know where the PHP code from step 3 should be placed?
Currently I have:
Step 1 (form): In the relevant page template.
Step 2 (jQuery): In a custom plugin, consisting of a PHP file and a JS file. PHP is shown below.
Step 3 (PHP): I currently have it placed as an ‘include’ in the php of the custom plugin. However I wonder if this is what you would suggest?
– I tried putting it directly in the page template but it didn’t work.
Right now my custom plugin php file looks like this…
I very sincerely appreciate your advice.
Hi Ben,
Try to use the Step 3 code in the
functions.php
of your current theme.default action return from admin-ajax.php
Hi Misha,
Awesome filter plug-in. It is doing exactly as I need.
Is there a way to reset the filter, without reloading the page?
Regards,
Rafael
Hi Rafael,
Well, ok, the first step is creating a button or link element with the ID #reset for example.
Second step is jQuery code, something like this:
Hello Misha,
Thank you, but sorry I wasn’t fully clear on my question earlier.
I have used this tutorial now to filter posts based on categories in WordPress.
At first it displays all the posts from all categories and the filter then displays posts only from a certain category.
Is it also possible to refresh / reload the filter so all posts from all categories are displayed again, and the filter is set back to the default selection?
Thank you
By the way,
I have found a solution to “reset” the dropdown button. If I could also reset to show all the posts, as before selecting a category, that would be perfect.
I have just re-checked the code and noticed I was missing a RETURN FALSE;
It works now!
After resetting the filter if you want to display posts from all categories, you can just resubmit the form.
Hello Misha,
I must be missing something, because when I click the “refresh” button all posts are displayed, but with /wp-admin/admin-ajax.php as URL and no styling anymore.
Sorry,
I was to fast replying. Managed to get it up working now.
Thank you very much for this tutorial!
Ok, great!
Hi Misha,
Just noticed that it does work, but only in Firefox and Safari.
If you could, can you see what I’m missing here? As only on Chrome it is not working…
You can also check it on letsmosh.nl
Hi Rafael,
How about refreshing your browser cache?
I have just re-checked the code and noticed I was missing a RETURN FALSE;
It works now!
I think I figured it out. I was using the Sage 9 theme, which has namespacing. So I had to add a \ to make the function call look like:
$query = new \WP_Query($args);
It works perfectly. Thank you so much for sharing this functionality!
Dude, you saved my life! I’m new to Sage 9 and overlooked this namespace business… I owe you a beer!
Misha thanks for sharing this! your posts are so amazing! Keep it up! <3
Always welcome,
Thank you for this inspiring comment ❤️
Hi, Misha!
Thanks for your code!
Pls, give me direction where to dig:
I have custom field “services” and multiple values (“cafe”, “sauna”, “kidclub”, etc).
So I want in form to put:
services:
[checkbox] cafe
[checkbox] sauna
[checkbox] kidclub
How to filter posts, which have checked checkboxes (meta_values) of one meta key?
I did in functions.php:
and in form:
But get «No posts found»
Where did I mistake? :((((
It seems I found solutions, maybe for someone it will be helpful
and add
in
form:
showing posts with at least 1 specified meta value…
It should be
but with ‘IN’ it shows nothing (((
Hi Sonica,
Your code looks good for radio buttons, not checkboxes.
Each checkbox should have different name attribute. And remove checkbox value attribute, let it be default
on
Hey! Thank you for your wonderful code! Such a very good work.
How can I filter multiple taxonomies with checkboxes?
For example:
Hey Alex,
It will be something like that :)
Misha, thank you so much! You helped me a lot!
Can you tell me if there a difference between admin-ajax and admin-post? I see that you used admin-ajax. Why this and not that?
Hi Talia,
Yes, it is. admin-post for all requests, admin-ajax – for Async requests only.
Hey,
Very good job !
But If i want use custom type and no default post WordPress ?
Where I add the name of my custom post please ?
Thank you !
Hi,
Thank you!
In Step 3 to the
$args
array, withpost_type
parameter.I want to filter categories by checkbox. How to do it?
To get the terms for the filter form you can use something like this:
To filter:
Hi Misha,
Love your work – its been really useful. One issue i’m having is keeping the standard WooCommerce Pagination after filtering my results – any idea’s? I’ve merged your loop in your example with the one i’m using on archive-products.php but its still not working
Hi Gemma,
Definitely it is not simple. I implemented the pagination code in Step 3 for my website but it was painful. And maybe you will need custom pagination function.
Hi Misha,
Your right it certainly is painful lol! I ended up realising that the standard WooCommerce pagination wasn’t going to be any good anyway as it reloads the page. I found your post about merging filters & load more posts – life saver! keep up the amazing work :-)
Great! 🙃
Thanks!
Thank you for this tutorial! Saved my bacon.
Hello Misha, Thanks for the great tutorial.
I sent you an email but made some progress, and maybe my issue can help others ?
I modified the code to submit the form on input change.
But the problem is that instead of adding the results to the #response div, the page goes to the URL “https://mysite.com/wp-admin/admin-ajax.php”. I assume that it comes from the AJAX request which must have a problem but I can’t find where as the hidden input is there and I tripled checked its value.
Could you take a look ?
Hi Marine,
Sorry, I have to remove your code – it doesn’t contain any useful information for me 🙃 People copy-paste their own code sometimes even without wrapping it with editor buttons hoping that I will write the code for them.
So, I understand your problem and let me point you to the correct way. If the page goes to
admin-ajax.php
, you have to check your browser console, in Chrome – right click on any element and then Inspect, choose the Console tab. It shows you all your JavaScript errors in the code.P.S. I don’t remember your emails.
Hello :) Thanks for your response ! ( It’s weird, I did wrap the code with the buttons ! )
I already checked the console, and what’s weird is that I don’t have any errors !
I figured that it might come from the wp_ajax_ filter, which is why I copied my code thinking it might be relevant !
In the end, I managed to fix my code. I was submitting the form on input change :
and doing the ajax request also on input change,
so on submit the page followed the action attribute, as the default behaviour.
I remove the onchange attribute from the input and it works now.
Thank you again for this great and useful tutorial :)
That’s great, I’m glad you’ve figured it out 🙃 Always welcome!
Got that to work, how about pagination? Would this be another jQuery function when click previous or next and add paged #? Thanks for any help you can provide.
I have no ready code for this task.
hi Misha,
i am trying to merge the info at premium.wpmudev.org/blog/load-posts-ajax in your code to get exactly the pagination to work, but am quite stuck…
i’m guessing that the main issue is with data:filter.serialize() whereby wpmu’s uses data:{action:’ajax_pagination’}
i’d be excellent (and i think it’ll complete your post with an important missing part – as well as becoming my new hero, of course! ;) if you could cast an eye on it and come up with your implementation?
Hi Max,
Do you mean pagination like on my website? Well, so much people asked me about that, I think soon will be the tutorial 🙃
hi Misha,
yes, that’s the one, something working along the line of paginate_links to have prev/#num#/next buttons to navigate through paged results from your code.
i do have a navigation script working just fine on the template which loads results the first time, before the filtering. as the site is using WooCommerce already, i’ve reused its styles and the output is similar to yours.
i think i’ve managed to add the “query_vars” to pass the “paged” value to the serialized data, but not the “page” value that tells the navigation script which page it’s been currently viewed and so it won’t output the prev/#num#/next – it always produces [1][…][0].
glad to know we’ve grown into an audience pressing you for the code ;) i guess it’s not surprise to you though, as the navigation is the missing cherry on the pie: posts number tends naturally to grow, so there ought to be a way to handle them in anything that deals their listing.
shame with ajax you have to reinvent the wheel, somehow. it’d have been great if there was WP support for that too (or maybe there’s but i’m too dumb to find it).
Do you know how I can get each filter to match the search query? I’m trying to include:
‘s’ => $search_query
to each array however I can’t seem to retrieve the search input in the function in functions.php. However I have no problem getting the search input in any other php file. Is this because it hasn’t been loaded in ajax? Any help will be appreciated.
And what is in
$search_query
? I suppose it is empty.Hi!
Superb tutorial, thank you very much! Was exactly what i needed.
Is it possible to dynamically change the button text to “show 123 posts” where 123 is the precalculated number of posts that will be shown?
Hi,
Thank you! :)
I think you have to send one more request, the simplified one. And use this
echo $query->found_posts;
to print the number of results.But the best practice is to combine these two requests using json response – in this case when you click the button, the posts won’t be loaded because they have been already loaded and will be displayed immediately.
Hi!
Thanks for your reply!
Can you give me a hint of how to combine the two requests?
I already managed to call 2 seperate functions – one for the result count and one for the results themselves.
In my understanding there must be a way to just write the HTML results in one variable/array(??) and the result count in a different variable/array(??). Then the ajax function that is called on filter changes returns the result count, and the ajax function that is called by submitting the form returns the HTML results.
Ok, I will try to describe you it in comments, but I think it is better to publish a tutorial about that.
First of all you have to set
dataType: 'json',
parameter in you AJAX call.Second – in your PHP
wp_ajax_
function create an array of two elements, json_encode it and print.Third, in your ajax call
success()
function you can usedata.html
anddata.count
properties.Something like that 🙃
Hello Misha,
Great code and it’s working perfectly as it is. I wonder whether you could help me to customise it to suit my requirement as with my limited PHP skills I’m pulling my hair to come up with a solution.
I have this custom field (not using ACF) attached to all my posts (standard WP posts) called ‘Read Time’. Basically I have a function that calculates read time of each posts and enter a number into that field. How can I create a filter to filter post with read times 1-5 minutes, 5-10 minutes and 11+ minutes? I did add this select to form but now struggling how to retrieve and compare the values to suit my query.
Any tips on this is highly appreciated. Many thanks in advance!
OK I managed to get that filter working using the following code. Not sure how ‘elegant’ the solution is but it is working.
Hey,
I’m glad you’ve figured it out and thanks for sharing your code. You solution is good. 🙃
Great description. I have almost managed to fit my needs this code.
How can I make an “all” option for the dropdown?
So if user do not select any (leaves its default state “all”) option from the dropdown all the options considered to be selected.
It is not enough information for me to give you an answer. Do you filter by terms or by post meta?
Hi Misha,
Can I ask why I’m having a response of 0? I have all my code exactly the way you coded it but some tweak with my own flow.
Thanks!
Hi,
Response 0 could happen if you didn’t connect
action
variable from your ajax call with appropriate action hook.I mean if
action=myaction
the hooks should bewp_ajax_myaction
andwp_ajax_nopriv_myaction
.Hey Misha,
This is an awesome post!
Is it also possible to pass some information into misha_filter_function()?
For example like:
The problem is I don’t understand how I can pass information into the function somewhere in step 1 or step 2.
Hope you can help me out!
Regards,
Maurits
Hey Bob,
This is very similar to submitting forms. You can add any fields to your form and after that you’re able to receive these parameters in
misha_filter_function()
from$_POST
array.Hej Misha,
thanks for that awesome post. I am actually searching for that kind of solution for filtering team members by position and location.
If i read right, in your solution you use a “Apply filter” Button. Is it possible to do the query automatically whenever a checkbox is changed?
Cheers Mike
@Mike Cosgrove
i’ve just applied this tweak on Misha’s code. change:
into:
and it should work.
Excellent code! How to deal with pagination?
Thank you.
The only way to deal with pagination is to create your own custom function for it.
Hello Misha, this was an excellent post, very useful and informative!
I would like to know about dealing with pagination as well. It would seem a logical addition to this otherwise great post, if I might add.
In my case, I have altered your code to suit my needs a little bit, and have tried to deal with the pagination but it gives an error when trying to click the links to the next page, after it successfully loads and shows the posts, AND updates the correct pagination. Instead of taking me to the correct page (i.e. blog/page/2), it takes me to another page (wp-admin/admin-ajax.php?paged=2).
I could add some of the code that I have used if that would help others.
In any case, thank you for your guidance!
Hello,
I receive many requests about pagination, so it seems like the post about it will be published soon.
Ah, excellent news. Thank you!
That post was also clutch, thanks for that.
Hi Misha, I’m getting only a number (0) as the response from the ajax call, not sure why that is, any ideas?
Nevermind, I solved it, thanks.
How did you solved it?
In many cases it means that the action parameter from your hidden field:
and from action hooks from
functions.php
doesn’t match:In this example the parameter is
myfilter
.How can I get term_id dynamically in the misha_filter_function() funtion?
I am using it on custom taxonomy archive page (in Custom Post Type). Please check code below
The above code is not working, but if i add term_id manually it works. But it is unable to get term id by its own. The reason for customizing above is, on custom taxonomy pages it is adding all posts in the loop while using filters.
Hi,
You can add it with the
$_POST
array.Thank you for the quick reply, but how can I get $_POST[‘term_id’] work inside misha_loadmore_ajax_handler(){} function and pass the value? I am talking about https://rudrastyh.com/wordpress/ajax-load-more-with-filters.html this article??
Somehow, I achieved this and now able to get the term_id misha_loadmore_ajax_handler(){} via ajax. Everything works fine the only problem is. It is duplicating the posts if we set the number of results through the per page filter.
how much posts it duplicates?
Same number of posts that are remaining in the loop. I’m simply trying to add a dropdown filter With a numeric meta field (custom post type, custom taxonomy). For example, if I set post per page to 5 and there are total 10 posts, first 5 post are loading correctly in queried order but after load more button click it load same 5 posts again. If I set post per page to 10, then it works perfectly.
I tested it a lot, but can’t figure it out. Your default code (twenty seventeen theme example) is also not working correctly. If we use filters the load more function doesn’t run correctly. Both works but only if we run them independently. (Ref: https://rudrastyh.com/wordpress/ajax-load-more-with-filters.html)
Hi Misha, On further digging I found that the loop parameter
is localizing/sending the default post query in all conditions. and in that case
will take the default query only. I think this line is the main culprit
and is not setting the new query parameters.
So when we use the filter it works and create the queried loop, but the load more function is not getting that loop and taking only the default post lopp.
Can you guide me how to fix this?
Hi again,
Didn’t you forget to change the posts_per_page value in
Settings > Reading
as well?I have tried that setting also. The only problem is, when we use post per page and other filters and call it. On first page or load it loads correct posts but on second page it loads posts from default template query instead of my filter query. You just test your default codes you will notice this.
Finally, After digging it for 4 days. I got the solution (which was pretty simple)
the above line is not inserting any query_vars set by our filter function. So it just keeps on showing posts from default loop for misha_loadmore_ajax_handler(){} function. The reason was
is returning a serilized form of data; not in JSON format. My fix is,
I am not sure, if above solution is the best. Please let me know if there could be any better solution?
I’m glad you’ve figured it out 🙃 But for me everything works good with
json_decode()
andjson_encode()
functions.Thank you Deepak and Misha. Great tutorial and great fix. I can confirm that Deepak is not crazy.
Howdy Misha,
Awesome tutorial! Well written and extreme helpful! 🙏
Hello.
First, what a beautiful tutorial, easier than a lot of other solution I crossed on the web.
Secondly, I’m sorry but I’m not English , sorry in advance for my poor language ;)
Thirdly , I’m not a Dev, or something like that, but I love puting my hands into the code and often I works :)
I spent 10 years on Magento and only discover WordPress now…. Woua, easier.
I have a question which is simple for you I think, and it’s more about PHP, or how to get data without a “loop”.
Into the function file, in your exemple, you suggest to call the title, and it works fine.
But me, I want to call a template part, with more data and PHP.
I success, BUT, on frontend, it call the template into the template, as many time there’s a post.
So it breaks all the HTML and I can’t manage the results.
For EXEMPLE : if my template would be,
On front, I get this :
How to call template as many time there is a result for post but with this displaying ?
MANY MANY THANKS :)
Hi,
Everything depend on the template part you include 🙃
Usually, while working with
get_template_part()
I recommend yo usequery_posts()
function insteadWP_Query()
.If the HTML structure is only issue you faced, you can add the closing/opening div element manually like this:
Thanks a lot for your fast answer, works very fine ;-)
Hello Misha,
I’m back again with a little question.
I red all the comments before on your article, spent a lot of time by myself searching on the web, trying things… before disturb you again.
I saw that others already tried to use two filters and I did it, it works fine :)
My little problem is, when I want to get only one filter, if one post isset and the other empty.
I think I’m didn’t have the php skills and I’m sorry.
Here’s the last code I’ve tried / you probably gonna laugh ;)
And, little “bonus question”. Did someone already ask about dynamics fields ? For exemple, if one activity is selected, display only destinations with results.
I think it would be hard to have this behaviour ?
Hi,
There should be an answer somewhere in comments, but I don’t remember where 🙃
So, here is the tip:
Bonus answer: No. And there is no short answer unfortunately.
Hello Misha,
First of all, thank you very much for your answer.
I read carefully again all the comments but didn’t see any solution.
Just to be sure, I don’t have a lot of skills in developpement, what you gave me is kind of theory ?
I have to complete much of the code ?
I’ve tried a lot of things but I’m not sure to understand how to modify my previous code into your new one.
Well I understand that you are not paid for all this help, that it takes time for you… if it’s too complicated to help me on this point, I will try to another solution :)
But if I find a solution, I’ll post it here for everyone :)
Thanks again.
Hello,
Strange, in fact I gave you the ready code 🙃
If you still didn’t resolve your problem, you can contact me by email (via Contact page).
Hello Misha,
I’ve sent you an email there already few days … Maybe you didn’t receive it or didn’t had the time to answer… but I understand :)
I have to finalize this work, I’ve tried again your code, the last little piece one, It still works for two filters / taxo, but for only one, there’s no results…
Is there some code to add ? Or something else ? I just want to have some results if there is only one taxonomy/filter :)
If you can’t help me, can you notice me, I’m gonna find another way, solution…
Thanks again and again !
Guillaume
Hey,
Strange, I didn’t remember your email, could you please send it to me one more time?
Hello Misha,
Thanks for your fast answer.
Strange… maybe it went into your spam, because of the PHP code or something else.
I made a more simple mail with access ;)
I wrote to you this morning (afternoon for you :).
Let me know if you need anything else.
Thanks again. Guillaume
This is a great tutorial. Thank you so much. It works great. Wondering if you have any ideas on how to make a “clear filters” button, so the filters are reset to null and all the posts show.
Thank you! 🙃
Sorry I removed your comment with code because it seems very unclear for me.
Here is step by step tip how to implement a “clear filters” button.
Step 1. Create a Clear Filters button
Let’s suppose that you would like to add it inside the
<form>
element. In this case you have to use<a>
HTML tag as a button.Step 2. Trigger the Event
It is about jQuery code. I used selectors and element IDs like in my tutorial. Add it inside
jQuery(function($){ ... });
Perfect!
Thank you for the great tutorial. I managed to get it working but when I filter my custom post type query the pagination doesn’t work. Instead all the navigation page links point to http://www.mysite.com/wp-admin/admin-ajax.php. Also, just to note that because
was not working (I use GeneratePress free theme) I has to install the Pagenavi plugin.
Is there an easy way to fix the pagination issue or do I have to do mind-boggling code workarounds like rewriting permalinks and stuff like that. I’m on a tight deadline here and have tried everything I can think of.
I have the same issue, trying to use wp_pagenavi.
Someone can help?
Hi,
Because it is the AJAX filter, it is not supposed to be a pagination here.
But if you really need it, I recommend you to look at the similar situation with pagination in this tutorial.
Misha I tried to use the code from the “Load More Posts Button + Numeric Pagination” tutorial for a query with a custom post type (inside a page template) with ajax filters but never managed to get it working even without the filters. Are you saying that is is possible to get a working pagination (with your custom pagination function) even after an ajax filter is clicked and the custom query has changed? Does the pagination have to be ajax based? I can’t see how the pagination links will work (www.mysite.com/pagetemplate/page/2) after an ajax filter has been applied meaning that the custom query will have changed.
Hey Misha thank you for sharing with us this amazing example.
I have a question, is there a way that i can check if select dropdown is selected with a specific value?
Hey,
I removed your code because you inserted it unformatted.
Do you mean this?
if( isset( $_POST['nameofselect'] ) && $_POST['nameofselect'] == 'UK' )
Hmm something like this, but all-cities is option value not the name of select, should it be like this?
Updated
Thank you very much, that really worked for me :)
Hi Misha,
Thanks for this!
Is there any way that I can simply use a list category links to switch out posts?
i.e. clicking on a category will filter the posts
Hey Pete,
The answer to your question is in this comment.
Thanks Misha,
I just want a list of links though, not a dropdown. Would it work the same way?
Yes, just use
click()
event instead ofchange()
.Thank you so much!
Hi Misha,
Are you planing for any tutorial on how to create woo commerce product filters based on different attributes?
Thanks
Ganesh
Hi Ganesh,
But WooCommerce allows to create this type of filter with widgets.
Hi Misha,
create code. It‘s really simple to read and understand it! :-)
I checked all the comments before, but does not find anything about that: Is it possible to show – like your screenshot – on every Categorie the count based on the filter settings?
Is it also possible to hide some categories based on the price filter settings?
E.g. I choose from 100$ to 1000$. But I do not have Products under 100$ in the category „Socks“ so its gonna be hide.
Hope you understand me and you have a Tipp for me?
Some kisses,
Angie ❤️
Hey Angie,
Yes, it is possible, I think you have to return in
wp_ajax_
andwp_ajax_nopriv_
action hooks not only the HTML of posts but also the posts count for each filter category.To do it, you have to return the data in json, example is here.
Hi great Tutorial thank you!
I have two post-types Indoors and Outdoors
How can I filter so people who choose Outdoors or Indoors and of course if neither is choosen then it would just display posts from both.
Thanks
Also 2 other notes please..
is there a way to default it so it displays all posts when entering when the page (so all displayed until your filter?)
And is there a way to clear all filters.
Thank you
Hi, thank you! 🙃
Actually all your questions were already discussed in comments below, but if you need my personal help with the code, you can contact me by email.
hello, how can you add pagination in this functionality? lets say for every execution you have 6 results per page, but if you have 12, you should have a pagination 1,2.. like that.. thanks!
Hello Elisa,
Already added, tutorial #1 and tutorial #2
Hello Misha, thank you for your excellent blog posts! They are very helpful, and I am so happy to have done this project without a plugin.
My question is if you have any idea or if it is even possible to capture the filter selections so that you could pass them between pages.
I have a separate query showing all posts before anything is filtered, and I have a search field and select boxes to filter taxonomies. So say I choose term1 and term2, then click a blog post from the results. Then I click a back button to return to all the posts. I want the posts to be filtered with the same selections.
I noticed that if you hit the back button, the select boxes retain their values, but the query still shows all the results.
Any knowledge you may have would be appreciated.
Thank you so much!!
Hey Beth,
If you would like the filter to save the value when you click back button, you must change the filter page URL when you filter posts. You can do it without AJAX
?param1=value1
or with changing a hash#param1=value1
Hi,
Can you briefly explain how to filter by tag, particularly in Step 3. PHP code to Process the Request? I am having difficulty getting the filter to work.
Thank you!
Hi Beth,
If you would like to filter by tag, you can also use
tax_query
parameter with'taxonomy'=>'post_tag'
Hi,
How I can use multipe radio buttons with same name and different values?
Regards,
Alex
Hi Alex,
The radio buttons you described can be used just like a regular
<select>
element in your PHP code.In HTML:
In PHP:
echo $_POST['yourname'];
Hi there, trying to get this to work on a custom post type archive, when I clear the filters it gets all the posts, not the custom post type. I’m guessing I need to modify the form to recognise which post type it is finding. Can this be done with admin-ajax.php?
Many thanks for your help, this works great except for that one detail
You need to change the function adding the post type:
This tutorial is very useful, i managed to learn how WordPress is working with Ajax. Thank you!
Hey Zod
Thanks very much, I’ve actually worked out how this works much more since my comment, I didn’t realise WordPress had such good ajax functionality!
Would you happen to know how to use the filter across multiple post types, I tried wrapping the post type in various if statements to test if it was on the custom post type archive page and the shop page however it returns 0 which I’m guessing is no products found?
Many thanks for your help!
Hi James, i think you just need to add them as Array, like so:
Hey Zod
That would return both post types on the one page
I’m trying to filter two different post types by their individual taxonomies as follows
Portfolio
– Portfolio Category (custom taxonomy)
Product
– gemstone
– gemstone shape
– setting type etc
Hello, thank you for your post! I am able to get the filter working but the results go to the url /wp-admin/admin-ajax.php
Shouldn’t the results be posted in the on the same page as the filter?
Hello,
Usually it happens because of a JavaScript error. Please check your browser console.
I was able to get this working. Thank you again for your post!
One thing though. Do you happen to know a way or can you point me to some documentation to add a search to this sort / filter form?
It is all about WP_Query orderby parameters. You can find it in official WordPress Codex.
Very nice, thank you!
I was wondering if you could help me, I want the date filter (ASC & DESC)to be in a “Select”.
Only the Desc is working, JS doesn’t show error and the posts load.
ps.: Sorry for my English
Oh and I use the code you provided*
Hey Samuel,
Thanks alot Misha!Damn how didn’t I see that !
I was wondering if you had other blogs/articles about this topic, I am new to wordpress development and I actually didn’t find alot of usefull guides. (Yours is the best!)
Im trying to filter my posts from 1 category by: Data, Title, Alphabetically and by popularity
Thanks again ! Have a good day !
Just this one…
Thank you so much 🙃 I wish you an awesome day too!
Hey Misha, I was unable to get a dropdown to sort by title with your code to sort by date. Any chance you could help or show me the direction?
Thanks (a great posts) !
Have a good day.
Finally I got it working if anybody need it.
Hey Misha !
I am trying to add a popularity filter… Cant get my head around how to implement it with your code.
Any chance you could help? Or give a a direction.
Thanks and have a good day.
Hey Sam,
How would you like to measure popularity? By views?
Hey Misha, good morning !
Yes, I think it is the easiest way?
(Now I have a dropdown to filter by Date Or Title and another dropdown to filter by ASC or DESC)
Thanks !
Hi Sam,
If you would like me to review your code or to help you with the code, directly on your website, please contact me by email.
Here in comments I can help you with an advice or some code snippets.
If you would like to filter posts by popularity, I think the best way is to use post meta with views, let’s say it will be
views
meta key.So, here are could be two steps:
1. Add a dropdown into the form, like this
2. In the step with PHP you can add the filtering like this:
I see there are two dropdown selects on your website, but the algorithm is the same 🙃
hi man thanks for you blog.
How can I filter taxonomy from another taxonomy for example:
Select 1: Countries: USA, Canada, Mexico
Select 2: Load states form selected country.
Thank you so much
Hi Juan,
Well, here is the detailed explanation. You mentioned something about another taxonomy – No, it must be the same hierarchical taxonomy, but states are child items of countries.
Step 1. jQuery event
When someone selects a country, the code will send AJAX request to receive its states.
Step 2. Process AJAX request in PHP
This code is for your
functions.php
file.Thanks for you help but I think I don’t explain the correct way.
I have two taxonomies: 1. Languages 2. Countries.
I’m triying do a filter post_type. When I create a post_type I can categorized it with language and country.
When the people choose a languages in the first select the second select will update and show the countries that have posts with the language choosed.
Thanks for your help.
Then change my Step 2 and write a function which will return countries depending on a selected language. Not sure how you will do it, to loop through all the post types doesn’t seem to me as a good idea. But if there is not so much posts, you can do it.
You can also consider using a single taxonomy.
Hi Misha,
I’ve rarely come across a tutorial or article where the author/dev gives so much personal time and code advice to commenters. It’s really impressive and thanks so much, this tutorial is going to be a great resource for me.
I have a few questions:
1. Instead of putting the misha_filter_function in the functions.php file, wouldn’t it make more sense to put that into a plugin? I’ve never seen a loop query done from within the functions.php file, and I’m wondering if that’s the most performant way to do it.
2. I have a custom post type archive page where I want to do the filtering, and instinctively I want to put the loop query code directly in the archive template. If I wanted to do that, how would I go about keeping the misha_filter_function in the functions.php file, while having the loop inside the archive template?
Thanks!
Hey Zach,
Thank you 🙃
1. Yes, definitely it could be done in a plugin or in a child theme. But in fact there is no difference, unless your theme receives updates.
2. Nope,
misha_filter_function()
should be always in thefunctions.php
/ plugin files.Awesome. Thanks for your response. :)
I was hoping you could help me with some advice/code snippet:
I have a custom post type, accommodation, and I have categories and tags as taxonomies for this CPT. I can get the category dropdown select to work or several tags as radio buttons. But how do I cross-filter by both categories and tags? When I create my tax_query it overrides the other tax_query, how do I merge them into a single cross-filtering tax_query so that I can filter by tags and categories both? Hope I’m explaining this correctly.
My Code:
Easy-breezy :)
Hello, Misha,
I want to make multiple selections, but it doesn’t show when I make multiple selections. Can you help me?
Thanks in advance.
Functions:
Frontend
Please check the above comment 🙃
Comments are closed.