I created a loop for my Custom Posts Type workshop with the lists of two custom taxonomies group and teacher on the same page. What I’m trying to do is create an Ajax filter with both taxonomies. The user can select one taxonomy or both to display a selection of posts.
The issues are when the user selects both taxonomies it only displays one post. And when he selects only one taxonomy the result displays “No posts found.”
Same thing for the button .filter-reset. I created it to reset the selection and display all the posts. Same issue, the result is “No posts found.”
Here is PHP code for the filter and the loop:
<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter" class="form-filter">
<div class="container">
<?php
if( $terms = get_terms( 'group', 'orderby=name&exclude=-1' ) ) :
echo '<div class="filter-tax filter--group">';
foreach ( $terms as $term ) :
echo '<input class="btn-radio" type="radio" name="categoryfilter1" value="' . $term->term_id . '"><label>' . $term->name . '</label>';
endforeach;
echo '</div>';
endif;
if( $terms = get_terms( 'teacher', 'orderby=name&exclude=-1' ) ) :
echo '<div class="filter-tax filter--teacher">';
foreach ( $terms as $term ) :
echo '<input class="btn-radio" type="radio" name="categoryfilter2" value="' . $term->term_id . '"><label>' . $term->name . '</label>';
endforeach;
echo '</div>';
endif;
?>
<a href="#" class="filter-reset">View all</a>
<input type="hidden" name="action" value="myfilter">
</div>
</form>
<?php
$query_args = array(
'post_type' => 'workshop',
'posts_per_page' => -1,
'orderby' => 'date'
);
$the_query = new WP_Query( $query_args );
if ( $the_query->have_posts() ) :
?>
<div class="wrapper-loop">
<?php
while ( $the_query->have_posts() ) :
$the_query->the_post();
get_template_part( 'template-parts/content-archive' );
endwhile;
?>
</div><!-- .wrapper-loop -->
<?php
else :
get_template_part( 'template-parts/content', 'none' );
endif;
?>
The PHP code for the AJAX function to filter the posts:
<?php
add_action('wp_ajax_myfilter', 'site_filter_function');
add_action('wp_ajax_nopriv_myfilter', 'site_filter_function');
function site_filter_function(){
$args = array(
'orderby' => 'date',
'posts_per_page' => -1
);
if( isset( $_POST['categoryfilter1'] ) && isset ($_POST['categoryfilter2']) ) {
$args['tax_query'] = array(
'relation' => 'AND',
array(
'taxonomy' => 'group',
'field' => 'id',
'terms' => $_POST['categoryfilter1']
),
array(
'taxonomy' => 'teacher',
'field' => 'id',
'terms' => $_POST['categoryfilter2']
),
);
} else {
if( isset( $_POST['categoryfilter1']) && !empty( $_POST['categoryfilter2'] ) )
$args['tax_query'] = array(
'taxonomy' => 'group',
'field' => 'id',
'terms' => $_POST['categoryfilter1']
);
if( isset( $_POST['categoryfilter2']) && !empty( $_POST['categoryfilter1'] ) )
$args['tax_query'] =
array(
'taxonomy' => 'teacher',
'field' => 'id',
'terms' => $_POST['categoryfilter2']
);
}
$query = new WP_Query( $args );
if( $query->have_posts() ) :
while( $query->have_posts() ): $query->the_post();
get_template_part( 'template-parts/content-archive' );
endwhile;
wp_reset_postdata();
else :
echo 'No posts found';
endif;
die();
}
?>
The JS code the AJAX:
( function($) {
$('.btn-radio').change(function(){
var filter = $('#filter');
$.ajax({
url:filter.attr('action'),
data:filter.serialize(),
type:filter.attr('method'),
beforeSend:function(xhr){
//filter.find('button').text('Processing...');
},
success:function(data){
//filter.find('button').text('Filter');
$('.loop-archive-workshop').html(data);
}
});
return false;
});
$(".filter-reset").click(function() {
document.getElementById('filter').reset();
$('.loop-archive-workshop').append();
var filter = $('#filter');
$.ajax({
url:filter.attr('action'),
type:filter.attr('method'),
data:filter.serialize(),
success:function(data){
$('.wrapper-loop').html(data);
}
});
return false;
});
} )(jQuery);
I’m struggling with this issue for days. Any help would be much appreciated!
EDIT
This is the content from the log.txt when using the fitler:
Array
(
[categoryfilter1] => 7
[action] => myfilter
)
Array
(
[categoryfilter1] => 5
[action] => myfilter
)
Array
(
[categoryfilter1] => 4
[action] => myfilter
)
Array
(
[categoryfilter1] => 7
[action] => myfilter
)
Array
(
[categoryfilter1] => 7
[categoryfilter2] => 14
[action] => myfilter
)
Array
(
[categoryfilter1] => 7
[categoryfilter2] => 8
[action] => myfilter
)
Array
(
[categoryfilter1] => 7
[categoryfilter2] => 16
[action] => myfilter
)
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
The problem seems to be in the checks you are performing in the php function that handles the ajax reguest.
The first if condition checks if both categoryfilter1 and categoryfilter2 properties are set the the $_POST, and then you have else.
Your code will never enter else because, from what I can see, you will always have at least one categoryfilter set at a given time.
I suggest using the following if conditions
if ((isset($_POST['categoryfilter1']) && !empty($_POST['categoryfilter1'])) && (isset($_POST['categoryfilter2']) && !empty($_POST['categoryfilter2']))) {
// both properties are set and have value (not empty)
} elseif ((isset($_POST['categoryfilter1']) && !empty($_POST['categoryfilter1'])) && (!isset($_POST['categoryfilter2']) || empty($_POST['categoryfilter2']))) {
// only categoryfilter1 is set and has value and categoryfilter2 is either not set or set but has no value
} elseif ((!isset($_POST['categoryfilter1']) || empty($_POST['categoryfilter1'])) && (isset($_POST['categoryfilter2']) && !empty($_POST['categoryfilter2']))) {
// only categoryfilter2 is set and has value and categoryfilter1 is either not set or set but has no value
}
This checks should handle all your possible outcomes
EDIT
To see the content of $_POST you can use PHP error_log, I use it all the time in development, it helps with displaying the content that you usually can’t output to the screen.
When using filters or ajax requests this can help because this are processes that happen on the backend.
error_log(print_r($_POST, true), 3, __DIR__ . '/log.txt');
error_log("rnrn", 3, __DIR__ . '/log.txt');
This code will create a new file named log.txt and will contain the content of $_POST.
If your ajax code is located in functions.php, the log.txt file will be in the same directory as functions.php.
After you are done remove the file, if you can’t, delete all content inside of it.
EDIT, after seeing log
The conditions can be even simpler looking at the content of $_POST, try this
if (isset($_POST['categoryfilter1']) && isset($_POST['categoryfilter2'])) {
// both are set
} elseif (isset($_POST['categoryfilter1']) && !isset($_POST['categoryfilter2'])) {
// only categoryfilter1 is set
} elseif (!isset($_POST['categoryfilter1']) && isset($_POST['categoryfilter2'])) {
// only categoryfilter2 is set
}
ALSO
Just noticed that for a single tax_query you use
$args['tax_query'] = array(
'taxonomy' => 'group',
'field' => 'id',
'terms' => $_POST['categoryfilter1']
);
This is incorrect, it should be like this
$args['tax_query'] = array(
array(
'taxonomy' => 'group',
'field' => 'id',
'terms' => $_POST['categoryfilter1']
)
);
tax_query expects an array, in that array you need to pass each taxonomy as its own array
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0