Easy Multiple filters using AJAX in just 20 minutes

During my projects, I have encountered many times the need of using easy multiple filters using AJAX, especially in WooCommerce projects. We are going to do this exactly on our Woo Commerce products. What is the reason? This technology is very much in demand right now and every one of us expects this filtering when we visit any shop page. While there are a ton of plugins that can do the job, on many occasions those plugins don’t have the exact functionality we need(for example custom taxonomies) or they are making the website performance very slow. You can read here how extensive usage of plugins harms the website.

Before we move on let’s start with an understanding of the basics of easy multiple filters using AJAX functionality following this post. There we have covered the basic process of how it happens for product filtering the process is not going to be much different, but we will just need to have more information passing from JS AJAX triggering code to a PHP function. Let’s start with a practical example of getting woo commerce products according to their lowest and highest prices and their alphabetical order.

Easy Multiple filters using AJAX
Easy Multiple filters using AJAX – final results

Easy Multiple filters using AJAX – Coding Process

First of all, let’s make sure that you have localized the script as described in the previous post about AJAX, but just in case you are having an uncaught reference error make sure to enqueue script with the same name as you are using in localization(first argument in both of them).

Easy Multiple filters using AJAX
Easy Multiple filters using AJAX – error because of wrong enqueuing

When the localization is done we need to follow the same process as we have done before. We need to create a PHP function that is going to be triggered by JavaScript code. We just need to make the right cases for our code. As soon as we are going to have a dropdown with the choice just make sure to have an HTML code where the select tag will have options where values will be numerical.

Easy Multiple filters using AJAX – The right way of enqueuing

We are going to transfer the values to PHP and use conditional logic there. If our value of the option tag will be 0 we will call arguments alphabetical order if the value will be 1 we will call products in descending order, and finally, in the case of 1, we will query products in the ascending order.

//Easy Multiple filters using AJAX - An example of HTML code
<div class="filter_products">
    <div class="col-xs-12">
      <select id="filter_paradise" class="form-control">
        <option value="0">Alphabetical</option>
        <option value="1">High Price</option>
        <option value="2">Low Price</option>
      </select>
    </div>
</div> 

//Jquery code triggering PHP function
jQuery('#filter_paradise').on("change", function() {

  valor = jQuery('#filter_paradise option:selected').val()
  changepost(valor)
  return

  function changepost(valor) {

  let value = valor
  jQuery.ajax({
    url: my_ajax_object.ajax_url,
    method: 'POST',
    data: {
      opc: value,
      action: 'filter_product',
      dataType: "json"
    },
    success: function(html, data) {
      jQuery('.products').replaceWith(html); 
    },
    error: function(errorThrown) {
      console.log(errorThrown)
    }
  })

 }
  
 // Easy Multiple filters using AJAX  - PHP code to be used in your functions.php file
 function filter_product(){
	$select_opc = $_POST['opc'];
	$last_uri = explode('/', $_SERVER['HTTP_REFERER']);
	$country = $last_uri[4];
	$getcategoria = explode('=',$last_uri[5]);
	$categoria = $getcategoria[1];
	// var_dump($last_uri);
	// var_dump($categoria);
	// var_dump($country);
	wp_reset_query();
  
	if (!empty($categoria)):
	  switch ($select_opc) {
		case 0:
		  $args = array( 
		  'post_type'           => 'product',
		  'post_status'         => 'publish',
		  'posts_per_page'      =>  -1,
		  'orderby'             => 'title',
		  'order'               => 'ASC',
		  'product_cat'         => $categoria,
		  'tax_query'           => array(
			  array(
			  'taxonomy'        => 'pa_country',
			  'terms'           => $country,
			  'field'           => 'name',
			  //'operator'        => 'IN'
			  )
			),
			'meta_query' => array(
				array(
					'key' => '_price',
					'value' => array(50, 100),
					'compare' => 'BETWEEN',
					'type' => 'NUMERIC'
				)
			)
		  );
		  break;
		case 1:
		  $args = array( 
		  'post_type'           => 'product',
		  'post_status'         => 'publish',
		  'posts_per_page'      =>  -1,
		  'meta_key'            => '_price',
		  'orderby'             => 'meta_value_num',
		  'order'               => 'DESC',
		  'product_cat'         => $categoria,
		  'tax_query'           => array(
			  array(
			  'taxonomy'        => 'pa_country',
			  'terms'           => $country,
			  'field'           => 'name',
			  //'operator'        => 'IN'
			  )
			  ),
			  'meta_query' => array(
				array(
					'key' => '_price',
					'value' => array(50, 100),
					'compare' => 'BETWEEN',
					'type' => 'NUMERIC'
				)
			)
		  );
		  break;
		case 2:
		  $args = array( 
		  'post_type'           => 'product',
		  'post_status'         => 'publish',
		  'posts_per_page'      =>  -1,
		  'meta_key'            => '_price',
		  'orderby'             => 'meta_value_num',
		  'order'               => 'ASC',
		  'product_cat'         => $categoria,
		  'tax_query'           => array(
			  array(
			  'taxonomy'        => 'pa_country',
			  'terms'           => $country,
			  'field'           => 'name',
			  //'operator'        => 'IN'
			  )
		 ),
		 'meta_query' => array(
				array(
					'key' => '_price',
					'value' => array(50, 100),
					'compare' => 'BETWEEN',
					'type' => 'NUMERIC'
				)
			)
		  );
		  break;
		default:
		  # code...
		  break;
	  }
	  else:
		switch ($select_opc) {
		  case 0:
			$args = array( 
			'post_type'           => 'product',
			'post_status'         => 'publish',
			'posts_per_page'      =>  -1,
			'orderby'             => 'title',
			'order'               => 'ASC',
			'product_cat'         => $country,
			'meta_query' => array(
				array(
					'key' => '_price',
					'value' => array(10, 100),
					'compare' => 'BETWEEN',
					'type' => 'NUMERIC'
				)
			)
			);
			break;
		  case 1:
			$args = array( 
			'post_type'           => 'product',
			'post_status'         => 'publish',
			'posts_per_page'      =>  -1,
			'meta_key'            => '_price',
			'orderby'             => 'meta_value_num',
			'order'               => 'DESC',
			'product_cat'         => $country,
			'meta_query' => array(
				array(
					'key' => '_price',
					'value' => array(10, 100),
					'compare' => 'BETWEEN',
					'type' => 'NUMERIC'
				)
			)
			);
			break;
		  case 2:
			$args = array( 
			'post_type'           => 'product',
			'post_status'         => 'publish',
			'posts_per_page'      =>  -1,
			'meta_key'            => '_price',
			'orderby'             => 'meta_value_num',
			'order'               => 'ASC',
			'product_cat'         => $country,
			'meta_query' => array(
				array(
					'key' => '_price',
					'value' => array(10, 500),
					'compare' => 'BETWEEN',
					'type' => 'NUMERIC'
				)
			 )
			);
			break;
		  default:
			# code...
			break;
		}
	  endif;
	$the_query = new WP_Query( $args );
  
	$salida = '<ul class="products">';
	  $salida .= '<div class="col-xs-12">';
		$salida .= '<div class="elementos_lista">';
		  $salida .= '<ul class="grid-sorting">';
		  if ( $the_query->have_posts() ) :
			while ( $the_query->have_posts() ) : $the_query->the_post();
			  $salida .= '<li>'; 
			  $product_thumbnail_url = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'thumbnail');
			  $url = get_permalink();
			  $salida .='<a href="'. get_permalink() .'">';
			  $salida .= '<div class="row list_product_paradise">';
			  if ($product_thumbnail_url):
				$salida .= '<div class="col-xs-2 image_product_thumbnail">';
				$salida .= '<img src="'. $product_thumbnail_url[0] .'" class="img-responsive" alt="'.get_the_title() .'">';
				$salida .= '</div>';
				$salida .= '<div class="product_cat col-xs-7">';
				$salida .= get_the_title();
				$salida .=  '</div>';
			  else:
				$salida .= '<div class="product_cat col-xs-9">';
				$salida .= get_the_title();
				$salida .=  '</div>';
			  endif;
			  $salida .='<div class="total_items col-xs-3">';
			  $salida .=  get_post_meta( get_the_ID(), '_regular_price', true);
			  $salida .=  '</div>';
			  $salida .=  '</div>';
			  $salida .=  '</a>';
			  $salida .= '</li>'; 
			endwhile;
		  endif;
		  $salida .=  '</ul>';
		$salida .=  '</div>';
	  $salida .=  '</div>';
	$salida .=  '</ul>';
	$salida .= '<div class="map_paradise"></div>';
	echo $salida;
	exit();
  
  }
  
	add_action( 'wp_ajax_filter_product', 'filter_product' );   
	add_action( 'wp_ajax_nopriv_filter_product', 'filter_product' );
  
 //Easy Multiple filters using AJAX - final results

Code explanation: We trigger the PHP function using Java Script’s change event. You can see online 52 how it works. We use cases and show each content according to what the user has chosen using cases. Additionally, I have also included a meta query where we choose the product by the price range too. I did not include it in the code leaving it up to you to make it if you need to.

Here is how to do it just save the min and max value in the variable in JavaScript and then in the PHP function instead of giving numbers in the array of meta query values just put the variables. And that is it.

Katen Doe

Hovhannes Verdyan

Hello, I’m a developer who loves WordPress and loves helping peopls let me know if you have any question by leaving your question in comments in one of my youtube videos. Click here to go to my channel.