In this post, I am going to share a simple way of using Ajax filter search for WordPress. I love using Ajax in my projects. It is neat, light and fast. Most importantly the user experience is much better.
The Scenario
We are going to build a search form like the one shown below. This form will search for movies which is a custom post type. We will also filter the result with a few fields – Movie Year, IMDB Rating, Language and Genre.
How Our Ajax Filter Search Works?
Ajax is very simple but can seem very tricky at first. In our scenario, we are going to send data as a request (search keywords, year, rating, language, genre) to the server and it will do a query with the data then return a callback with the results.
Initial Setup
For the purpose our ajax filter search form, we may create a fresh WordPress install and populate dummy data for the trial. We will basically edit 2 files in the theme – functions.php and script.js. As always, please make sure you are using a child theme. I used the Twenty Sixteen Theme’s child theme in my demo. I added a custom post type called movie and created the custom fields with Advanced Custom Fields plugin. You can add a custom post type with the following code added to the functions.php file.
<?php
function register_custom_post_type_movie() {
$args = array(
"label" => __( "Movies", "" ),
"labels" => array(
"name" => __( "Movies", "" ),
"singular_name" => __( "Movie", "" ),
"featured_image" => __( "Movie Poster", "" ),
"set_featured_image" => __( "Set Movie Poster", "" ),
"remove_featured_image" => __( "Remove Movie Poster", "" ),
"use_featured_image" => __( "Use Movie Poster", "" ),
),
"public" => true,
"publicly_queryable" => true,
"show_ui" => true,
"show_in_rest" => false,
"has_archive" => false,
"show_in_menu" => true,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => false,
"rewrite" => array( "slug" => "movie", "with_front" => true ),
"query_var" => true,
"supports" => array( "title", "editor", "thumbnail" ),
"taxonomies" => array( "category" ),
);
register_post_type( "movie", $args );
}
add_action( 'init', 'register_custom_post_type_movie' );
Code language: HTML, XML (xml)
Alternatively, you can use a plugin like Custom Post Types UI for adding custom post types with a user interface.
Before we create some movie posts, we need to create the custom fields which are used as filters.
The fields are pretty self-explanatory but if you are confused, here is the exported JSON file of the field group which you can download, unzip and import on ACF.
Download acf-export-2018-04-02.zip
Once you have the custom fields ready, you can start posting some movie posts. The add new movie post page should look something like the following.
You can see, I added some categories. They will work as the genre of the movie. After creating some demo movie posts, we are ready to start coding.
Creating a Shortcode for the Ajax Filter Search
In this step, we are creating a shortcode that will return the form code. So, we can use the shortcode in any part of the website to use the form. Put the following code on functions.php file.
<?php
// Shortcode: [my_ajax_filter_search]
function my_ajax_filter_search_shortcode() {
ob_start(); ?>
Test Shortcode Output
<!-- FORM CODE WILL GOES HERE -->
<?php
return ob_get_clean();
}
add_shortcode ('my_ajax_filter_search', 'my_ajax_filter_search_shortcode');
Code language: HTML, XML (xml)
Now use the shortcode [my_ajax_filter_search] in any page content and you should see “Test Shortcode Output” as output. As our shortcode is working fine, we are going to put actual form code that we will use the filter/search form.
<?php
// Shortcode: [my_ajax_filter_search]
function my_ajax_filter_search_shortcode() {
ob_start(); ?>
<div id="my-ajax-filter-search">
<form action="" method="get">
<input type="text" name="search" id="search" value="" placeholder="Search Here..">
<div class="column-wrap">
<div class="column">
<label for="year">Year</label>
<input type="number" name="year" id="year">
</div>
<div class="column">
<label for="rating">IMDB Rating</label>
<select name="rating" id="rating">
<option value="">Any Rating</option>
<option value="9">At least 9</option>
<option value="8">At least 8</option>
<option value="7">At least 7</option>
<option value="6">At least 6</option>
<option value="5">At least 5</option>
<option value="4">At least 4</option>
<option value="3">At least 3</option>
<option value="2">At least 2</option>
<option value="1">At least 1</option>
</select>
</div>
</div>
<div class="column-wrap">
<div class="column">
<label for="language">Language</label>
<select name="language" id="language">
<option value="">Any Language</option>
<option value="english">English</option>
<option value="korean">Korean</option>
<option value="hindi">Hindi</option>
<option value="serbian">Serbian</option>
<option value="malayalam">Malayalam</option>
</select>
</div>
<div class="column">
<label for="genre">Genre</label>
<select name="genre" id="genre">
<option value="">Any Genre</option>
<option value="action">Action</option>
<option value="comedy">Comedy</option>
<option value="drama">Drama</option>
<option value="horror">Horror</option>
<option value="romance">Romance</option>
</select>
</div>
</div>
<input type="submit" id="submit" name="submit" value="Search">
</form>
<ul id="ajax_filter_search_results"></ul>
</div>
<?php
return ob_get_clean();
}
add_shortcode ('my_ajax_filter_search', 'my_ajax_filter_search_shortcode');
Code language: HTML, XML (xml)
Here, we added 5 fields. The search as an input field, Year as a number field, Rating, Language and Genre as a select dropdown. The options in the drop-down fields are set based on the option we had in the custom fields. The year field will have 4 digit number so it is ok with as a number field. Rating is set from 1 to 9 as IMDB ratings are like that. Language and Genre are ordinary select fields with matching options from the backend custom field and categories.
Adding Necessary Script
We are going to create a new script.js file in our theme folder for adding our javascript codes. Add the following code before the shortcode function we added earlier on the functions.php file.
<?php
// Scripts for Ajax Filter Search
function my_ajax_filter_search_scripts() {
wp_enqueue_script( 'my_ajax_filter_search', get_stylesheet_directory_uri(). '/script.js', array(), '1.0', true );
wp_add_inline_script( 'my_ajax_filter_search', 'const ajax_info = '. json_encode( array(
'ajax_url' => admin_url( 'admin-ajax.php' )
) ), 'before' );
}
Code language: HTML, XML (xml)
We also used wp_inline_script() for easy use of admin-ajax.php file.
Next thing to do is calling the my_ajax_filter_search_scripts() function inside the my_ajax_filter_search_shortcode() function.
<?php
// Shortcode: [my_ajax_filter_search]
function my_ajax_filter_search_shortcode() {
my_ajax_filter_search_scripts(); // Added here
ob_start(); ?>
<div id="my-ajax-filter-search">
<form action="" method="get">
....
....
Code language: HTML, XML (xml)
This way the scripts needed for the ajax filter/search will load whenever we use the shortcode.
Preparing Data for Sending the Request
Add the following code to the script.js file
$ = jQuery;
var mafs = $("#my-ajax-filter-search");
var mafsForm = mafs.find("form");
mafsForm.submit(function(e){
e.preventDefault();
console.log("form submitted");
// we will add codes above this line later
});
Code language: JavaScript (javascript)
Here we added two variables for ease of use and then a function that fires when the form submit button is pressed. The code e.preventDefault(); part prevents page reload. You will also see output “form submitted” on browser console (Press F12 on Chrome to go to developer tools and then Esc to go to console window).
Now that we see our code is working fine, we can go ahead and prepare the data. Replace console.log(“form submitted”); with the following code (before “});” at the bottom).
if(mafsForm.find("#search").val().length !== 0) {
var search = mafsForm.find("#search").val();
}
if(mafsForm.find("#year").val().length !== 0) {
var year = mafsForm.find("#year").val();
}
if(mafsForm.find("#rating").val().length !== 0) {
var rating = mafsForm.find("#rating").val();
}
if(mafsForm.find("#language").val().length !== 0) {
var language = mafsForm.find("#language").val();
}
if(mafsForm.find("#genre").val().length !== 0) {
var genre = mafsForm.find("#genre").val();
}
var data = {
action : "my_ajax_filter_search",
search : search,
year : year,
rating : rating,
language : language,
genre : genre
}
Code language: JavaScript (javascript)
Here, we are checking on submission, if the fields have value. If they do, we set their respective value on a variable and add all of them to the variable data. The part action : “my_ajax_filter_search” is needed for the callback in the next step as we will be sending data via GET method.
Prepare Callback Function
We have the data ready for the request. Now, we need to configure the callback. Going back to the functions.php file, we will add a new function for the callback.
<?php
// Ajax Callback
add_action('wp_ajax_my_ajax_filter_search', 'my_ajax_filter_search_callback');
add_action('wp_ajax_nopriv_my_ajax_filter_search', 'my_ajax_filter_search_callback');
function my_ajax_filter_search_callback() {
header("Content-Type: application/json");
$meta_query = array('relation' => 'AND');
if(isset($_GET['year'])) {
$year = sanitize_text_field( $_GET['year'] );
$meta_query[] = array(
'key' => 'year',
'value' => $year,
'compare' => '='
);
}
if(isset($_GET['rating'])) {
$rating = sanitize_text_field( $_GET['rating'] );
$meta_query[] = array(
'key' => 'rating',
'value' => $rating,
'compare' => '>='
);
}
if(isset($_GET['language'])) {
$language = sanitize_text_field( $_GET['language'] );
$meta_query[] = array(
'key' => 'language',
'value' => $language,
'compare' => '='
);
}
$tax_query = array();
if(isset($_GET['genre'])) {
$genre = sanitize_text_field( $_GET['genre'] );
$tax_query[] = array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => $genre
);
}
$args = array(
'post_type' => 'movie',
'posts_per_page' => -1,
'meta_query' => $meta_query,
'tax_query' => $tax_query
);
if(isset($_GET['search'])) {
$search = sanitize_text_field( $_GET['search'] );
$search_query = new WP_Query( array(
'post_type' => 'movie',
'posts_per_page' => -1,
'meta_query' => $meta_query,
'tax_query' => $tax_query,
's' => $search
) );
} else {
$search_query = new WP_Query( $args );
}
if ( $search_query->have_posts() ) {
$result = array();
while ( $search_query->have_posts() ) {
$search_query->the_post();
$cats = strip_tags( get_the_category_list(", ") );
$result[] = array(
"id" => get_the_ID(),
"title" => get_the_title(),
"content" => get_the_content(),
"permalink" => get_permalink(),
"year" => get_field('year'),
"rating" => get_field('rating'),
"director" => get_field('director'),
"language" => get_field('language'),
"genre" => $cats,
"poster" => wp_get_attachment_url(get_post_thumbnail_id($post->ID),'full')
);
}
wp_reset_query();
echo json_encode($result);
} else {
// no posts found
}
wp_die();
}
Code language: HTML, XML (xml)
The above code block has few important things that I would like to explain.
- At line 05 and 06, you see we used add_action for the callback function my_ajax_filter_search_callback(). If you have been using a diffrent function name, you can change wp_ajax_my_ajax_filter_search to wp_ajax_YOUR_FUNCTION_NAME. Same thing for wp_ajax_nopriv_my_ajax_filter_search
- At line 10 we added header(“Content-Type: application/json”); to declare the content type as json because, we are going to use JSON to send result back to the browser.
- At line 12 we started adding meta_query rules based on our fields. They are checked if they are set from the form submission then, they are sanitized for injection and compared different conditions.
- At line 41 we added tax_query rules as we used WordPress categories as the Genre of the movies.
- Finally, at line 52, we combined the arguments for the query but we also need to query for the search keywords passed from the search input. For this, we used ‘s’ => $search. Here the value of $search is checked for relevant results.
- After the query, at line 95 we echo the result encoded as JSON which we will use in the next step in jQuery Ajax function.
jQuery Ajax Function
Now we are going to use jQuery Ajax function to complete our last step. Add the following code after the previous code (before the bottom “});”) on script.js file.
$.ajax({
url : ajax_info.ajax_url,
data : data,
success : function(response) {
mafs.find("ul").empty();
if(response) {
for(var i = 0 ; i < response.length ; i++) {
var html = "<li id='movie-" + response[i].id + "'>";
html += " <a href='" + response[i].permalink + "' title='" + response[i].title + "'>";
html += " <img src='" + response[i].poster + "' alt='" + response[i].title + "' />";
html += " <div class='movie-info'>";
html += " <h4>" + response[i].title + "</h4>";
html += " <p>Year: " + response[i].year + "</p>";
html += " <p>Rating: " + response[i].rating + "</p>";
html += " <p>Language: " + response[i].language + "</p>";
html += " <p>Director: " + response[i].director + "</p>";
html += " <p>Genre: " + response[i].genre + "</p>";
html += " </div>";
html += " </a>";
html += "</li>";
mafs.find("ul").append(html);
}
} else {
var html = "<li class='no-result'>No matching movies found. Try a different filter or search keyword</li>";
mafs.find("ul").append(html);
}
}
});
Code language: JavaScript (javascript)
Here you can see we used ajax_info.ajax_url that we defined on the functions.php file. We then used the data variable for data param and for the success we have set a response.
As we are going to search multiple times from the same page, we will need to empty the ul that will contain all the results before appending the results. So we used mafs.find(“ul”).empty();
At last, we did a for loop and prepared the layout of the result to the html variable.
mafs.find(“ul”).append(html); appends the result in the ul.
Let us add some quick CSS so that it all looks good. You can add it to the sytle.css file or custom CSS in customizer.
.column-wrap {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
margin: 20px 0
}
.column-wrap .column {
width: 49%;
}
.column-wrap .column:last-child {
float: right;
}
#my-ajax-filter-search label {
display: block;
font-weight: bold;
font-style: italic;
}
#my-ajax-filter-search select {
width: 100%;
background-color: #f7f7f7;
padding: 0.625em 0.4375em;
border: 1px solid #d1d1d1;
}
#ajax_filter_search_results {
list-style: none;
display: flex;
justify-content: start;
flex-wrap: wrap;
margin-top: 30px;
}
#ajax_filter_search_results li {
width: 23.5%;
float: left;
margin-right: 2%;
overflow: hidden;
position: relative;
margin-bottom: 20px;
}
#ajax_filter_search_results li.no-result {
width: 100%;
text-align: center;
}
#ajax_filter_search_results li:nth-child(4n+4) {
margin-right: 0;
}
.movie-info h4 {
margin-bottom: 10px;
color: #fff;
}
.movie-info p {
margin-bottom: 0;
color: #fff;
font-size: 13px;
}
.movie-info {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
padding: 15px;
background: rgba(0, 0, 0, 0.85);
opacity: 0;
display: flex;
flex-wrap: wrap;
align-items: center;
transition: all .3s;
}
.movie-info * {
width: 100%;
display: block;
}
#ajax_filter_search_results li:hover .movie-info {
opacity: 1;
}
Code language: CSS (css)
The Output!
Bonus
A lot of requests came in since this article was published. One of the major requests was to know how to use checkboxes for the filter. So, let me share that with you guys.
To use checkboxes you will need to modify the code in a few areas. First of all, you need to make sure the checkboxes are added properly. If you are going to take multiple values, they need to be prepared so the values can be used in the query.
I am adding an example to the existing setup so you can follow:
First, add a new field in the field group for the checkboxes. Check the screenshot
In the form right before the submit field, let’s add an extra checkbox group
<input class="available" type="checkbox" id="netflix" value="netflix" name="available"><label for="netflix">Netflix</label>
<input class="available" type="checkbox" id="amazon" value="amazon" name="available"><label for="amazon">Amazon</label>
<input class="available" type="checkbox" id="viki" value="viki" name="available"><label for="viki">Viki</label>
<input class="available" type="checkbox" id="blueray" value="blueray" name="available"><label for="blueray">BlueRay</label>
Code language: HTML, XML (xml)
Then, let’s add the javascript part. Here we are taking the values of the checkboxes to an array.
var available = [];
$.each($("input[name='available']:checked"), function(){
available.push($(this).val());
});
Code language: JavaScript (javascript)
Now inside the my_ajax_filter_search_callback()
function before the genre meta_query conditon, let’s add some code
if(isset($_GET['available'])) {
$available = $_GET['available'];
foreach( $available as $value ) {
$meta_query[] = array(
'key' => 'available_on', // our new added custom field for the checkboxes
'value' => $value,
'compare' => 'LIKE'
);
}
}
Code language: PHP (php)
Now your query should return according to the checkbox checked or unchecked properly.
Hopefully, this article will help you try Ajax on your next WordPress project and you will be easily adding an ajax filter search form on your website. Feel free to share your feedback below. Happy Coding!
Credits: Banner image from Freepik by macrovector. Movie posters are for demo purposes only. I don’t hold any copyright for the movie posters visible at the screenshots or anywhere else.
111 comments
Jim Poulos
Hello Al-Mamun,
This is excellent. Thanks very much. I am currently having 99% success. However, when the search does not match, I am not getting the “no results found” message. For example if I choose a genre which includes 3 results, no problems. I get the 3 movies that match. But if I choose a language or genre that I know has no matches, it does not empty the container and will not show a no results found message. Any ideas?
Al-Mamun Talukder
It works on my demo page, not sure why it doesn’t work for you. Please check the browser console for the error log.
Carl
Great Tutorial! Any chance that this could include some pagination on the results?
Dimitar
Very Helpful! Thank you for you work and that you share this!
Mahesh
Good Work and Good Example.
Thank You
Vikas Pandey
Hello,
How we can add pagination in this example. I need to add paginate links function for pagination
Appreciate your response
Thanks
Vikas
Hello,
how we can display the default results on page load
Appreciate your response
Thanks
Al-Mamun Talukder
Do a regular query on the page once ajax is done, replace that content with results.
Hussain Saad
how can i make it custom post type (plugin)
and i want to add filter by date
thanks in advance
Jon Imms
awesome tutorial thank you. I was wondering, is there solution like this without having to click the search button? So displays results as soon as you select a dropdown item
Al-Mamun Talukder
You can change the javascript code to trigger submission on change of dropdown item or any other fields
Saravan
Can we make the AJAX to trigger on click of the select elements rather than click on Search each time
Al-Mamun Talukder
Yes. Just change javascript portion to trigger submission on change of select elements or any other fields that you may require.
Shivam gohil
can you send me that all files please?
also how can i data show by default
Al-Mamun Talukder
You need to do a WP_Query inside the results div to show data by default. Files are not available for share right now.
Patzki
Finally found an awesome solution. Thanks for this OP 😀
dhanan
Hi it’s a nice tutorial, everything works fine. but the checkbox code you mentioned as bonus its not working properly. when i check amazon its show both amazon,viki,Netflix results, i uploaded only 3 checkbox with 3 dummy data. problem is, when i check the amazon or any check value it shows all the results which is wrong, it should show only the particular data.kindly share me the functions.php page full code, i think the placement of the checkbox code mistake.
Lucas
Hi bro,
Great tips, but I want to show all posts before using ajax filter search, what should I do?
Thank bro!
Al-Mamun Talukder
Hi Lucas. Just a default query within the shortcode’s code. For example:
Replace the following code from the shortcode function..
[html]<ul id="ajax_filter_search_results"></ul>[/html]
With
[php]
<?php
$args = array(
‘post_type’ => ‘movie’,
‘posts_per_page’ => -1,
);
$default_query = new WP_Query( $args );
if ( $default_query->have_posts() ) {
echo ‘<ul id="ajax_filter_search_results">’;
while ( $default_query->have_posts() ) {
$default_query->the_post();
/** YOUR QUERY LOOP HERE **/
}
wp_reset_postdata();
echo ‘</ul>’;
}
?>
[/php]
MG
hey! I really like what you did here and the way you respond/explain everyone how to use your code, well done!
The only thing I wanted to ask: in functions.php you have your function my_ajax_filter_search_shortcode(), but you manually add the options for Year, IMDB Rating, Language, Genre. Is it possible to automatically pick up those options from database instead of writing them down? In your ACF plugin you will have your fields, can’t we just list all the values under options dynamically instead of typing them out? Because now – if you will add new Genre in admin, you will have to go and edit this script to make it visible on front end.
Al-Mamun Talukder
Hello. Thanks for your comment. Certainly possible. For most users, the regular way is OK and easier but as you mentioned, it is in fact better to dynamically load the options. Please check this out for reference https://www.advancedcustomfields.com/resources/dynamically-populate-a-select-fields-choices/
Heather New
I’m having a hard time with the callback and ajax portion. I’m not using a CPT, I have a section repeater that has a Q&A faq repeater nested inside. To display acf fields in php I use:
[html]<a href="” rel="nofollow ugc">
<a href="” target=”_blank” rel="nofollow ugc">
<a href="” target=”_blank” rel="nofollow ugc">
——————————————
This is my callback attempt
function faq_ajax_filter_search_callback() {
header(“Content-Type: application/json”);
$meta_query = array(‘relation’ => ‘AND’);
$args = array(
‘post_type’ => ‘page’,
‘meta_query’ => $meta_query
);
if(isset($_GET[‘search’])) {
$search = sanitize_text_field( $_GET[‘search’] );
$search_query = new WP_Query( array(
‘post_type’ => ‘page’,
‘meta_query’ => $meta_query,
‘s’ => $search
) );
} else {
$search_query = new WP_Query( $args );
}
if ( $search_query->have_posts() ) {
$result = array();
while ( $search_query->have_posts() ) {
$search_query->the_post(); ?>
get_the_ID(),
“section” => have_rows(‘section’),
“section_headline” => get_sub_field(‘section_headline’),
“section_faq” => have_rows(‘section_faq’),
“headline” => get_sub_field(‘headline’),
“headline” => get_sub_field(‘headline’),
“information” => get_sub_field(‘information’),
“button” => get_sub_field(‘button’),
);?>
<?php }
wp_rest_query();
——————-[/html]
Would be super appreciative for help, I'm learning how to make acf data dynamic
Heather
hah, no worries. Thank you for sharing this solution, it was a helpful example. I’ve got it in and working my next step is to modify it a bit to work with nested repeaters and using ACF fields on a page instead of through a CPT to create an ajax search for a FAQ page.
Heather
In the shortcode above there is a ul looks to be misspelled as fitler not filter
Al-Mamun Talukder
Well, that was embarrassing. Thanks for pointing that out. I fixed the issue 🙂
Alexandr
For repeater field we need to add this code. Now it works
add_filter(‘posts_where’, ‘yanco_posts_where’);
function yanco_posts_where( $where ) {
$where = str_replace( “meta_key = ‘repeater_machines_$”, “meta_key LIKE ‘repeater_machines_%”, $where );
$where = str_replace( “meta_key = ‘repeater_machines_$”, “meta_key LIKE ‘repeater_machines_%”, $where );
return $where;
}
Can you help me to handle with the problem ?
How I can do a search only when all search fields are filled in, we just not need to search until all fields are filled. Now it searches even one field is filled.
Thanks for your work!
Al-Mamun Talukder
You can make the fields required (in your form code), in that case, all fields will need to be filled before it searches.
Alexandr
Hello. How I can search by repeater field. With simple txt field search works perfectly, but when I try to add repeater field it doesn’t work. COUNTRY – is the repeater field.
I think the mistake is in this part:
if(isset($_GET['country'])) {
$country = sanitize_text_field( $_GET['country'] );
$meta_query[] = array(
'key' => 'country',
'value' => $country,
'compare' => '='
);
}
or in this one:
if( have_rows('repeater_machines') ):
while ( have_rows('repeater_machines') ) : the_row();
$country = get_sub_field('country');
endwhile; endif;
//wp_reset_query();
$result[] = array (
"id" => get_the_ID(),
"title" => get_the_title(),
"content" => get_the_content(),
"permalink" => get_permalink(),
"year" => get_field('year'),
"rating" => get_field('rating'),
"director" => get_field('director'),
"language" => get_field('language'),
"test" => get_field('test'),
"country" => $country,
"genre" => $cats,
"poster" => wp_get_attachment_url(get_post_thumbnail_id($post->ID),'full')
);
}
Can you help me, please?
Al-Mamun Talukder
Try ‘compare’ => ‘LIKE’
Quentin
No worries ! Thanks a lot !
matt
thank you for this tutorial. I can’t resolve an issue. Dev tools keep throwing me an error “data is not defined” in the script.js field, there :
$.ajax({
url : ajax_url,
data : data,
i can’t understand why.
Al-Mamun Talukder
You missed a step in code. Please review the JS file. ‘data’ was defined earlier before ‘$.ajax….’
Theresa
Hi I haven’t tried it yet, but is there a way to have the list showing on the page but it is filtered once you use the form?
Al-Mamun Talukder
You can easily do it. Just do the query on page load then empty the queried posts div with the results from the ajax call.
Quentin
Hello and thanks for this tutorial !
I saw on previous comments that you were talking about pagination, I tried a few things but I still can’t manage to set up the pagination (or load more button) system correctly.
Would it be possible for you to put an example as a bonus?
Thank you
Al-Mamun Talukder
Sorry, have been busy. I will post that soon.
Kamila Bona
Hi! I’m not good enough at js. Where should I make changes in the code?
Kamila
Hello! Great tutorial.
I would like to search for movies from date to date. For example, all releases from 1/6/2019 to 1/3/2020. I think I have a problem with the date format.
Paulo
Thank you sir, this helped me a lot!
Santanu Patra
It was my mistake that meta_key was different. It’s now working really smoothly. But now I want to fetch post names in the dropdown from a CPT.
Customizing the my_ajax_filter_search_shortcode() function to get post categories using get_terms. But not working.
Sorry, but can’t share with you the URL at this moment. I will try to understand my points.
Santanu Patra
Hei.. Thanks for this amazing concept. I want to use this queries to find post depending on 2 custom field value. I used the above code and customized. But every time all post appear.
Al-Mamun Talukder
Hi. Please share the URL so I can check. It should work out of the box. I would suggest you do it first on a clean WordPress install.
Ido
Hi, thank you so much for this tutorial, helped me a lot.
I would like to display results in php post loop (probably in the functions.php file), instead of the jquery result. Is there a way for that?
Thanks
Al-Mamun Talukder
If you want to change a post loop, you need to replace that with what we did here. In short, its something different and out of the scope of this tutorial.
Jeff
Thank you for this! How would you use this and turn it into a checkbox filter of categories post?
Al-Mamun Talukder
Hello Jeff. I added an extra bonus section to the content about the checkbox field. Please check it here https://itsmereal.com/simple-ajax-filter-search-for-wordpress/#bonus
Dmitry Yudin
Hello, thx a lot for that tutorial! It’s really helpful!
But checkboxes filter does not work for me.. If I check it all posts are shown.
Where I am wrong with code?
Адсорбент
Все
[code]
if(isset($_GET[‘animal’])) {
$animal = sanitize_text_field( $_GET[‘animal’] );
$meta_query[] = array(
‘key’ => ‘animal’,
‘value’ => $animal,
‘compare’ => ‘=’
);
}
[/code]
[code]
$ = jQuery;
var mafs = $("#my-ajax-filter-search");
var mafsForm = mafs.find("form");
mafsForm.submit(function(e){
e.preventDefault();
// console.log("form submitted");
if(mafsForm.find("#search").val().length !== 0) {
var search = mafsForm.find("#search").val();
}
if(mafsForm.find("#animal").val().length !== 0) {
var animal = mafsForm.find("#animal").val();
}
if(mafsForm.find("#genre").val().length !== 0) {
var genre = mafsForm.find("#genre").val();
}
var data = {
action : "my_ajax_filter_search",
search : search,
animal : animal,
genre : genre
}
[/code]
When I checked ‘ adsorbent’ field or uncheck it I see only one page with ‘adsorbent’ but when I uncheck it, it shows me only this one page anyway…
Al-Mamun Talukder
Hello Dmitry Yudin,
To use checkboxes you will need to modify the code in a few areas.
First of all, you need to make sure the checkboxes are added properly. If you are going to take multiple values, they need to be prepared so the values can be used in the query.
I am adding an example to the existing setup so you can follow:
First, add a new field in the field group for the checkboxes. Check the screenshot https://imgur.com/a/VOVocHD.
In the form right before the submit field, let’s add an extra checkbox group
[html]
<input class="available" type="checkbox" id="netflix" value="netflix" name="available"><label for="netflix">Netflix</label>
<input class="available" type="checkbox" id="amazon" value="amazon" name="available"><label for="amazon">Amazon</label>
<input class="available" type="checkbox" id="viki" value="viki" name="available"><label for="viki">Viki</label>
<input class="available" type="checkbox" id="blueray" value="blueray" name="available"><label for="blueray">BlueRay</label>
[/html]
Then, let’s add the javascript part. Here we are taking the values of the checkboxes to an array.
[javascript]
var available = [];
$.each($("input[name=’available’]:checked"), function(){
available.push($(this).val());
});
[/javascript]
Now inside the my_ajax_filter_search_callback() function before the genre meta_query conditon, let’s add some code
[php]
if(isset($_GET[‘available’])) {
$available = $_GET[‘available’];
foreach( $available as $value ) {
$meta_query[] = array(
‘key’ => ‘available_on’, // our new added custom field for the checkboxes
‘value’ => $value,
‘compare’ => ‘LIKE’
);
}
}
[/php]
Now your query should return according to the checkbox checked or unchecked properly.
Joey
I’m very novice at JS. How would I do that?
Al-Mamun Talukder
Add this inside the form
<input id="reset_form" type="reset" value="Reset">
Then, add the following in your js file. (after $ = jQuery; line)
$("#reset_form").click(function(){
mafs.find("ul").empty();
});
Joey
That’s great! Can I have it clear the results Div too so that the search results disappear too?
Al-Mamun Talukder
Yes. Set this on click of the reset button with javascript.
mafs.find("ul").empty();
Joey
This is great! Is there a way to clear the search and reset fields? Ie a “clear” button? That way users don’t manually have to reset everything between results?
Al-Mamun Talukder
Hello Joey. It’s easy to add a Reset button. Just add this inside the form code.
<input type="reset" value="Reset">
Steven
Thanks for your response ! I have try some things, but I’m not good enough in Javascript to understand what I have to do to be able separating the form part and the search result part. In this way to be able to put the form somewhere and display the search result (WP_query) somewhere else.
Will apreciate alot if you could give me some more indication of how to do it.
kindly,
Steven
Al-Mamun Talukder
Please contact through the Live Chat or Contact Page
Steven
Unfortunately is what I have trying. When I take the ul element outsite of the -> “div id=”my-ajax-filter-search”
The ul is displaying nothing 🙁
Al-Mamun Talukder
It is not working outside of the #my-ajax-filter-search because, it is used on the javascript portion of the code. You need to change javascript code so the correct ID is used to perform the ajax request.
Steven
Hello! Great tutorial, but is there a way to display the “ul -> li elements” somewhere else?
If u put the “ul ->li elements” somewhere else, it is not working.
I would like to have the form at the end of my page and the result of the search at the middle.
Al-Mamun Talukder
Hello Steven. Please try taking this
Anatolie
Hi!
When the language in WP admin panel is English, the search works correctly but when I switch it to German or German (Austria) for some words or phrases the search results are strange!
For example, when I search “Es ist was nicht war” having WordPress switched to German, instead of 2 posts (events) I am getting all posts, with different titles.
Any Idea how to fix this error, Please?
Al-Mamun Talukder
If you are searching for “Es ist was nicht war” and your content, title or any meta that you are searching in, has any matching words, it should list the post. Es, ist, was – these can be in regular words so it is normal to show more results. You can tweak the search results by changing the meta compare.
Anatolie
In this special case the search is just in post title (not in post page and not in meta).
Fragments as Es, ist, was are of course contained in other words, like etwas, Junges etc.
I have about 300 events but this problem happens only with this title and it does not happen when I switch to English in admin settings.
There is something additional that WP changes when I change the language..
For me is important to get correct search response based on event title. Based on it, I get in ‘Next Presentations” block all events with the same title which will take place in future and other places.
Anatolie
Hello and thank you for the tutorial!
Is it possible to search by text not only in Title and post content but also in meta fiels, such as subtitle 1, subtitle 2?
Al-Mamun Talukder
Thanks for your comment. You can easily search meta fields. Just add conditions as you need them. Here is a quick example.
if(isset($_GET['subtitle_1'])) {
$subtitle_1 = sanitize_text_field( $_GET['subtitle_1'] );
$meta_query[] = array(
'key' => 'subtitle_1',
'value' => $subtitle_1,
'compare' => 'LIKE'
);
}
Anatolie
Thanks for quick answer!! 🙂
For this example should be also created corresponding fields in the form, Subtitle 1, Subtitle 2, correct?
My question is: can we extend the search area of the search field to the meta fields? The keyword inserted in the search filed to be searched in post tile, post content, meta subtitle 1, meta subtitle 2.
Al-Mamun Talukder
Yes. You need to create custom fields and add the fields to the form. Then you need to pass the from data, where the query will try to search for similar content (title, content and any other fields you mention).
Anatolie
I have implemented this filter for my Events custom posts. It is working fine. Thank you!
But I would like to NOT add additional text fields to the form, in order to search in custom fields Subtitle 1, Subtitle 2. What I want is to use just one, existent form field for search in all event text, including meta fields.
Al-Mamun Talukder
Then you just need to add the extra meta query for subtitle 1 and subtitle 2 fields, which will search with the existing variable data taken from the form search input.
Jonathan THOMAS
Hi ! Very good job ! Thanks a lot.
Is there a way that we could add autocompletion when typing for search please ?
Al-Mamun Talukder
In the javascript portion of the code where we have
mafsForm.submit(function(e){
e.preventDefault();
you can use this
$("#search").on('keyup keypress blur change', function() {
if($(this).val().length > 3) {
This will trigger the search once a minimum of 4 characters are typed. Don’t forget to adjust the rest of the code accordingly otherwise it will not work.
pttuan
The code works great, but when I entered the wrong movie title, the result didn’t return “No matching movies found. Try a different filter or search keyword”. Can you check it for me please
Al-Mamun Talukder
I am using the same code that is given here and it works fine in the demo. Please double check your code to see if there is any difference. Thanks.
pttuan
Thks, i find problem. Jquery new not support it. I tried wordpress default jquery and got it done
Sheraz
Thanks for this great tutorial. i am using custom taxonomy in my form for woocommerce products i want to show the taxonomy terms title & want to add “add to cart button” with their link so the user can go to the cart page.
Scott
I can’t seem to get ajax to kick in – when I do a search, all that happens is the page reloads. What is the best way to dubug an AJAX form to know where the problem is? I’ve tried adding the exact code into my custom them as well as 2016 multiple times…. Thanks!
Scott
I figured it out!
The instruction to add:
my_ajax_filter_search_scripts(); // Added here
Was very subtle and I missed it! Thanks!
lloydM
WOW! You really help me out of my problem. hehe
the best tutorial I have read.
Emil D.
Thanks, great tutorial!
But how do i create a page (for GoogleAds for example) showing only posts with certain filters already on load of the page? Let’s say i want to have a URL which shows all movies from the year 2012 on load – how would i do that? I tried playing around in the URL, as i see the “?search=&year=&rating=&language=&genre=&submit=Search” part there, but nothing happens if i insert “2012” after the “year=” part for example and hit enter.
Al-Mamun Talukder
You need to change the JavaScript code to initiate everything on page load. In this tutorial, I did it on submit. Then it will work the way you want.
Maria
Great outstanding tutorial! May I know how can I search with multiple keywords like spiderman, xman etc? Would appreciate your response alot
Al-Mamun Talukder
Hello Maria. You will need to modify the WP_Query part of this tutorial to achieve search with multiple keywords. I am using ‘s’ which is the default search. In your case, it will need to be meta_query.
Mary
Hi, thank you for this great tutorial. I have one question. If etc. director name contains Ö or Ä, it doesn’t show in results, it’s O or A there. How to fix this?
Al-Mamun Talukder
Hello Mary. The director name field is not being searched in this tutorial. I will test the special letters.
Mary
Thank you for your quick reply 🙂
I think better way to explain this problem is thinking of option value, which must be lowercase and not containing special characters.
Etc. Räv return “rav” although it shoud return “Räv” in response[i].animal.
So how can it set it return “Räv”?
Hope this helps.
Mary
Sorry, tags was gone in my message.
https://ibb.co/yRb5nHk
Al-Mamun Talukder
Can you please ping me on live chat so I can take a look at the issue?
vaheed
Thank you for sharing this post. Its working for me.
vaheed
hi,
I am facing the issue with custom filed checkbox.
PLease check here: https://www.whichbroker.com/en/brokers/
As per your instruction i was followed your comments for checkbox method.
Here my code:
in function
if(isset($_GET[‘mutual_funds’])) {
$mutual_funds = $_GET[‘mutual_funds’];
$meta_query[] = array(
‘key’ => ‘tradable_assets’, // This needs to be the ACF field key
‘value’ => $mutual_funds,
‘compare’ => ‘LIKE’
);
}
if(isset($_GET[‘currencies’])) {
$currencies = $_GET[‘currencies’];
$meta_query[] = array(
‘key’ => ‘tradable_assets’, // This needs to be the ACF field key
‘value’ => $currencies,
‘compare’ => ‘LIKE’
);
}
‘compare’ => ‘IN’ => not working for me.
so i was given ‘compare’ => ‘LIKE’ its showing result but its not correct results.
please check my form fields for check box. something is missing in my code. please have a look once.
Dean
Thanks a lot for your work! With the tutorial, I nearly finish my dream filter. Could you please share more thoughts about the pagination or ajax ‘load more’ button? I’ve tried, but it doesn’t work well.
Beat regards & thanks again.
Jason
Hi, this is great. Thanks for helping! I do have one question, what if one of the fields were a checkbox group? How would the jquery change from this, for example, if year were a checkbox group?:
if(mafsForm.find(“#year”).val().length !== 0) {
var year = mafsForm.find(“#year”).val();
}
Al-Mamun Talukder
var checkedYear = [];
$(".year:checkbox:checked").each(function() {
checkedYear.push($(this).val());
});
Something like this. It’s important to note that for checkbox you will need to use array on form element name attribute. For example:
<label><input type="checkbox" name="year[]" class="year" value="2019"> 2019</label>
Jason
Thanks! Still having some issues. I’m hoping you can help me out.
I have this in my form:
2019
2020
———-and this in the .js file
var mafs = $(“#my-ajax-filter-search”);
var mafsForm = mafs.find(“form”);
var checkedyear = [];
$(“.year:checkbox:checked”).each(function() {
checkedyear.push($(this).val());
});
However I get the error:
ReferenceError: year is not defined
Do you know whey that is? Thanks.
Al-Mamun Talukder
ReferenceError: year is not defined
This error is because you don’t have the class year on your form checkbox input.
Jason
If I change the following:
var data = {
action : “my_ajax_filter_search”,
search : search,
checkedyear : checkedyear,
}
I don’t get the reference error, but I get all of the posts rather than just the 2019 posts, for example.
Al-Mamun Talukder
You will need to add extra arguments to the WP_Query function
if(isset($_GET['checkedyear'])) {
$year = $_GET['checkedyear'];
$meta_query[] = array(
'key' => 'year', // This needs to be the ACF field key
'value' => $year,
'compare' => 'IN'
);
}