Create an asynchronous AJAX filter, which allows to filter posts by taxonomy terms and meta values.
See live working filter here
Create a page template template-resources.php
<?php
/**
* Template Name: Resources Page
*/
$blog_posts_query = new WP_Query([
'post_type' => 'resources',
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'AND', // redundant default value 'AND' but I still put it in..
array(
'taxonomy' => 'resources_cat',
'field' => 'id',
'terms' => 'resources',
//'terms' => array(39,40,41,42,43,44,45,46,47),
),
)
]);
?>
<?php get_header(); ?>
<?php partial('partials/hero'); ?>
<div class="wrapper" id="page-wrapper">
<div class="resources-section s-pt-6 s-pb-6">
<div class="container">
<div class="row">
<div class="col-md-4">
<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter">
<div class="filters">
<h2>Search Resources</h2>
<div class="quicksearch-container">
<span class="material-icons">search</span><input type="text" name="quicksearch" class="quicksearch" placeholder="Search Keyword ..." />
</div>
<?php // Get the taxonomy's terms
$terms = get_terms(
array(
'taxonomy' => 'resources_cat',
'hide_empty' => false,
)
);
// Check if any term exists
if ( ! empty( $terms ) && is_array( $terms ) ) { ?>
<div class="ui-group ui-group-type d-none">
<p>Publications: </p>
<select name="categoryfilter">
<option value="">All</option>
<?php foreach ( $terms as $term ) { ?>
<option value="<?php echo $term->term_id; ?>"><?php echo $term->name; ?></option>
<?php } ?>
</select>
</div>
<?php } ?>
<div class="ui-group ui-group-type">
<p>Type: </p>
<select name="typefilter">
<option value="">All</option>
<option value="video">Video</option>
<option value="article">Article</option>
<option value="whitepaper">Whitepaper</option>
<option value="posters-presentations">Posters & Presentations</option>
<option value="sds">SDS</option>
</select>
</div>
<div class="ui-group ui-group-product">
<p>Product: </p>
<select name="productfilter">
<option value="">All</option>
<option value="mt-prep-extraction">MT-Prep Extraction</option>
<option value="puryx-extraction">Puryx Extraction</option>
<option value="mt-pcr">MT-PCR</option>
<option value="robotic-platforms">Robotic platforms</option>
</select>
</div>
<div class="ui-group ui-group-topic">
<p>Topic: </p>
<select name="topicfilter">
<option value="">All</option>
<option value="covid19">COVID19</option>
<option value="respiratory">Respiratory</option>
<option value="enteric-pathogens">Enteric Pathogens</option>
<option value="urinogenital-hpv">Urinogenital & HPV</option>
<option value="drug-resistance">Drug Resistance</option>
<option value="critical-testing">Critical testing</option>
<option value="fungal">Fungal</option>
<option value="genetics">Genetics</option>
<option value="small-animals">Small animals</option>
<option value="livestock">Livestock</option>
<option value="agricultural-farming">Agricultural & Farming</option>
<option value="water-testing">Water testing</option>
<option value="food-testing">Food testing</option>
</select>
</div>
<div class="ui-group ui-group-date">
<p>Year: </p>
<select name="yearsfilter">
<option value="">All</option>
<option value="2005">2005</option>
<option value="2006">2006</option>
<option value="2007">2007</option>
<option value="2008">2008</option>
<option value="2009">2009</option>
<option value="2010">2010</option>
<option value="2011">2011</option>
<option value="2012">2012</option>
<option value="2013">2013</option>
<option value="2014">2014</option>
<option value="2015">2015</option>
<option value="2016">2016</option>
<option value="2017">2017</option>
<option value="2018">2018</option>
<option value="2019">2019</option>
<option value="2020">2020</option>
<option value="2021">2021</option>
</select>
</div>
<div class="button-group">
<button class="btn btn-primary">Apply Filter</button>
<input type="hidden" name="action" value="myfilter">
</div>
</div>
</form>
</div>
<div class="col-md-8">
<div id="response">
<?php if ($blog_posts_query->have_posts()): ?>
<?php while ($blog_posts_query->have_posts()): ?>
<?php $blog_posts_query->the_post(); ?>
<?php $file = get_field('file');
$name = get_field('display_file_name');
$updated = get_field('add_updated_date');
$note = get_field('note');
$icon = get_field('add_file_icon');
$link = get_field('link');
$video = get_field('video', false, false);
/* FILTERS */
$types = get_field('filter_types');
$products = get_field('filter_products');
$topics = get_field('filter_topics');
$years = get_field('filter_years'); ?>
<div class="color-shape resource <?php if( $types ): foreach( $types as $type ): echo $type.' '; endforeach; endif; if( $products ): foreach( $products as $product ): echo $product.' '; endforeach; endif; if( $topics ): foreach( $topics as $topic ): echo $topic.' '; endforeach; endif; echo $years;?>">
<?php if( $file || $link || $video): ?>
<?php if(!empty( $link)):
$link_url = $link['url'];
$link_title = $link['title'];
$link_target = $link['target'] ? $link['target'] : '_self'; ?>
<a href="<?php echo esc_url( $link_url ); ?>" target="<?php echo esc_attr( $link_target ); ?>">
<?php else: ?>
<?php if( $icon == 'download' ): ?>
<a href="<?php echo $file['url']; ?>" target="_blank" download>
<?php elseif( $icon == 'video' ): ?>
<a href="<?php echo $video; ?>" target="_blank">
<?php else: ?>
<a href="<?php echo $file['url']; ?>" target="_blank">
<?php endif; ?>
<?php endif; ?>
<?php if( $icon == 'link' ) {
echo '<span class="iconify" data-icon="eva:external-link-fill" data-inline="false"></span>';
}elseif( $icon == 'download' ) {
echo '<span class="iconify" data-icon="bx:bxs-download" data-inline="false"></span>';
}elseif( $icon == 'video' ) {
echo '<span class="iconify" data-icon="dashicons:format-video" data-inline="false"></span>';
}else{
echo '<span class="iconify" data-icon="mdi-file-pdf" data-inline="false"></span>';
} ?>
<?php echo get_the_title() ?> <?php if( $name ): echo '<span>('.$name.')</span>'; endif; ?> <?php if( $note ): echo '<span>('.$note.')</span>'; endif; ?> <?php if( $updated ): echo '<span>('.$updated.')</span>'; endif; ?></a>
<?php else: ?>
<?php echo get_the_title() ?> <?php if( $name ): echo '<span>('.$name.')</span>'; endif; ?> <?php if( $note ): echo '<span>('.$note.')</span>'; endif; ?> <?php if( $updated ): echo '<span>('.$updated.')</span>'; endif; ?>
<?php endif; ?>
</div>
<?php endwhile; ?>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
<!-- <?php //nu__display_section_builder(); ?> -->
<!--?php if (!get_field("disable_cta")): ?>
<?php //partial('partials/global--cta-section'); ?>
<?php //endif; ?> -->
</div>
<?php get_footer();
Add JS Code resources.js
;(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;
});
})(jQuery)
Add PHP Code for resource
<?php $file = get_field('file');
$name = get_field('display_file_name');
$updated = get_field('add_updated_date');
$note = get_field('note');
$icon = get_field('add_file_icon');
$link = get_field('link');
$video = get_field('video', false, false);
/* FILTERS
$types = get_field('filter_types');
$products = get_field('filter_products');
$topics = get_field('filter_topics');
$years = get_field('filter_years'); */ ?>
<div class="resource">
<?php if( $file || $link || $video): ?>
<?php if(!empty( $link)):
$link_url = $link['url'];
$link_title = $link['title'];
$link_target = $link['target'] ? $link['target'] : '_self'; ?>
<a href="<?php echo esc_url( $link_url ); ?>" target="<?php echo esc_attr( $link_target ); ?>">
<?php else: ?>
<?php if( $icon == 'download' ): ?>
<a href="<?php echo $file['url']; ?>" target="_blank" download>
<?php elseif( $icon == 'video' ): ?>
<a href="<?php echo $video; ?>" target="_blank">
<?php else: ?>
<a href="<?php echo $file['url']; ?>" target="_blank">
<?php endif; ?>
<?php endif; ?>
<?php if( $icon == 'link' ) {
echo '<span class="iconify" data-icon="eva:external-link-fill" data-inline="false"></span>';
}elseif( $icon == 'download' ) {
echo '<span class="iconify" data-icon="bx:bxs-download" data-inline="false"></span>';
}elseif( $icon == 'video' ) {
echo '<span class="iconify" data-icon="dashicons:format-video" data-inline="false"></span>';
}else{
echo '<span class="iconify" data-icon="mdi-file-pdf" data-inline="false"></span>';
} ?>
<?php echo get_the_title() ?> <?php if( $name ): echo '<span>('.$name.')</span>'; endif; ?> <?php if( $note ): echo '<span>('.$note.')</span>'; endif; ?> <?php if( $updated ): echo '<span>('.$updated.')</span>'; endif; ?></a>
<?php else: ?>
<?php echo get_the_title() ?> <?php if( $name ): echo '<span>('.$name.')</span>'; endif; ?> <?php if( $note ): echo '<span>('.$note.')</span>'; endif; ?> <?php if( $updated ): echo '<span>('.$updated.')</span>'; endif; ?>
<?php endif; ?>
</div>
Add Codes in function.php
add_action('wp_ajax_myfilter', 'brens_filter_function'); // wp_ajax_{ACTION HERE}
add_action('wp_ajax_nopriv_myfilter', 'brens_filter_function');
function brens_filter_function(){
$args = array(
'post_type' => 'resources',
'posts_per_page' => -1,
'orderby' => 'date', // we will sort posts by date
'order' => $_POST['date'],
'tax_query' => array(
'relation' => 'AND', // redundant default value 'AND' but I still put it in..
array(
'taxonomy' => 'resources_cat',
'field' => 'id',
'terms' => 'resources',
//'terms' => array(39,40,41,42,43,44,45,46,47),
),
)
);
// SEARCH
//if( isset( $_POST['quicksearch']) && $_POST['categoryfilter'] ):
if( isset( $_POST['quicksearch']))
$search_query = sanitize_text_field( $_POST['quicksearch'] );
$args = array(
'post_type' => 'resources',
'posts_per_page' => -1,
's' => $search_query,
'orderby' => 'date',
'order' => $_POST['date'],
'tax_query' => array(
'relation' => 'AND', // redundant default value 'AND' but I still put it in..
array(
'taxonomy' => 'resources_cat',
'field' => 'id',
//'terms' => $_POST['categoryfilter'],
'terms' => 'resources',
//'terms' => array(39,40,41,42,43,44,45,46,47),
),
)
);
/*else:
$search_query = sanitize_text_field( $_POST['quicksearch'] );
$args = array(
'post_type' => 'resources',
's' => $search_query,
'orderby' => 'date',
'order' => $_POST['date'],
'tax_query' => array(
'relation' => 'AND', // redundant default value 'AND' but I still put it in..
array(
'taxonomy' => 'resources_cat',
'field' => 'id',
'terms' => array(39,40,41,42,43,44,45,46,47),
),
)
);
endif;*/
// TYPE
if( isset( $_POST['typefilter'] ) )
$args['meta_query'][] = array(
'key' => 'filter_types',
'value' => $_POST['typefilter'],
'compare' => 'LIKE'
);
// PRODUCT
if( isset( $_POST['productfilter'] ) )
$args['meta_query'][] = array(
'key' => 'filter_products',
'value' => $_POST['productfilter'],
'compare' => 'LIKE'
);
// TOPIC
if( isset( $_POST['topicfilter'] ) )
$args['meta_query'][] = array(
'key' => 'filter_topics',
'value' => $_POST['topicfilter'],
'compare' => 'LIKE'
);
// YEARS
if( isset( $_POST['yearsfilter'] ) )
$args['meta_query'][] = array(
'key' => 'filter_years',
'value' => $_POST['yearsfilter'],
'compare' => 'LIKE'
);
// 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 partial('partials/resource');
endwhile;
wp_reset_postdata();
else :
echo '<p>No resources found</p>';
endif;
die();
}
SCSS Code for the resources page
body.page-template-template-resources,
body.page-template-template-resources-test{
.filters{
@include pr(calc(8.33333% + 30px));
@include mb(2rem);
@include media-breakpoint-down(lg) {
@include pr(30px);
}
@include media-breakpoint-down(md) {
@include pr(0);
}
.quicksearch-container{
border-bottom: 2px solid $grey;
@include py(1rem);
height: 54px;
@include mt(2rem);
.material-icons{
color: $link-colour;
font-size: 1rem;
}
input{
border: none;
font-size: 0.875rem;
font-weight: $font-weight-semibold;
color: $link-colour;
width: calc( 100% - 1rem);
&:active, &:focus{
outline: none;
background-color: none;
}
}
}
.ui-group{
border-bottom: 2px solid $grey;
position: relative;
display: block;
width: 100%;
p{
@include py(1rem);
float: left;
font-size: 0.875rem;
font-weight: $font-weight-semibold;
color: $link-colour;
@include mb(0);
height: 54px;
}
select{
float: right;
border: none;
@include py(1rem);
font-size: 0.875rem;
font-weight: $font-weight-semibold;
color: $link-colour;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none; /* Remove default arrow */
background-image: url('../img/select-drop-down-grey.png');
background-repeat: no-repeat;
background-position: right center;
background-size: 16px 16px;
&:active, &:focus{
outline: none;
}
}
&:after{
content:"";
display: block;
clear: both;
}
&-type{
select{
width: calc( 100% - 86px );
}
}
&-product{
select{
width: calc( 100% - 86px );
//width: calc( 100% - 57px );
}
}
&-topic{
select{
width: calc( 100% - 86px );
//width: calc( 100% - 40px );
}
}
&-date{
select{
width: calc( 100% - 86px );
//width: calc( 100% - 38px );
}
}
}
.button-group{
@include mt(2rem);
.btn{
min-width: 100%;
&:focus, &:active{
outline: none;
}
}
}
}
.grid,
#response{
@include mt(1rem);
&:after {
content: '';
display: block;
clear: both;
}
}
.resource{
@include mb(2rem);
position: relative;
font-size: 1.125rem;
font-weight: $font-weight-light;
width: 100%;
.iconify{
color: $secondary;
position: absolute;
top:4px;
left: 0;
font-size: 1.125rem;
width: 20px;
height: 20px;
}
a{
color: $text-colour;
@include pl(1.5rem);
display: block;
transition: all 0.3s ease;
&:hover{
text-decoration: none;
color: $secondary;
}
span{
color: $link-colour;
}
}
}
}
* { box-sizing: border-box; }