wp query – WordPress Ajax form filter | Search by title with ajax form, breaks the other filters
I have implemented a form within my code that gives the user the possibility to filter the products according to his needs.
The form was created in ajax, to increase the user experience level of the user
Step:
-
I implement this code on the page where I want the form to appear
<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter"> <input autocomplete="off" type="search" class="form-control rounded" name="search" id="search" style="min-width: 225px" /> <?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: + costosto </label> <label> <input type="radio" name="date" value="DESC" selected="selected" /> Date: - costoso </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>
-
I create a file: custom.js and insert this code
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; }); });
-
I call my js file, in functions.php
wp_enqueue_script( 'CUSTOM-JS', get_template_directory_uri() . '/Custom.js', array(), '1.0.0', true);
-
I always implement this code in functions.php
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( 'posts_per_page' => -1, 'post_type' => 'produtcs', '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' => 'metakey_AMC_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' => 'metakey_AMC_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' => 'metakey_AMC_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 if( !empty( $_POST['search'] )) $args = [ 's' => $_POST['search'], ]; add_filter( 'posts_where', 'title_filter', 10, 2 ); $query = new WP_Query( $args ); remove_filter( 'posts_where', 'title_filter', 10, 2 ); if( $query->have_posts() ) : while( $query->have_posts() ): $query->the_post(); echo '<h2>' . $query->post->post_title . '</h2>'; $price = get_post_meta( get_the_ID(), 'metakey_AMC_price', true ); echo $price ; endwhile; wp_reset_postdata(); else : echo 'No posts found'; endif; die(); } function title_filter( $where, &$wp_query ){ global $wpdb; if ( $search_term = $wp_query->get( 'search_prod_title' ) ) { $where .= ' AND ' . $wpdb->posts . '.post_title LIKE '%' . esc_sql( like_escape( $search_term ) ) . '%''; } return $where; }
if you want to try this code by copying and pasting without these parts, go ahead, replacing post_type either with your cpt or with post
code to be removed if you want in functions.php | step 4:
if( !empty( $_POST['search'] ))
$args = [
's' => $_POST['search'],
];
add_filter( 'posts_where', 'title_filter', 10, 2 );
remove_filter( 'posts_where', 'title_filter', 10, 2 );
the code works perfectly and does its own.
The problem arises when I implement the search input field, (search bar), which by writing the parameters and giving enter finds the results by filtering in the title of the custom post type, but when I want to have title + any other filter together then it stops working.
I wrote if you want to remove that piece of code to show that all the code without that piece has filters used in combination as it should be.
I get the problem only when I want
-
I search for product by name and I get it
-
use another filter of those available
Plus: I think the problem is in writing this piece:
if( !empty( $_POST['search'] ))
$args = [
's' => $_POST['search'],
];
how can i fix?
Leave an answer