Ajax filter with custom taxonomies

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

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x