0

I have a loop for my Custom Posts Type workshop filtered with two custom taxonomies group and teacher on the same page. The Ajax filter works perfectly.

Each links of the filter works with a <input type="checkbox">, for both taxonomies lists. When the user selects one or multiple terms in the filter, then unselects all of them, the filter returns "No posts found" because nothing is selected.

What I would like to do is, when the user unselects all the terms in the filter it displays all the posts of my Custom Posts Type.

The PHP code of the filter for the frontend:

<form action="<?php echo site_url() ?>/wp-admin/admin-ajax.php" method="POST" id="filter">

  <div>
  <?php
    if( $groups = get_terms( array( 'taxonomy' => 'group' ) ) ) :
      echo '<ul class="groups-list">';
      foreach( $groups as $group ) :
         echo '<input type="checkbox" class="" id="group_' . $group->term_id . '" name="group_' . $group->term_id . '" /><label for="group_' . $group->term_id . '">' . $group->name . '</label>';
       endforeach;
       echo '</ul>';
     endif;
   ?>
   </div>

   <div>
   <?php
     if( $teachers = get_terms( array( 'taxonomy' => 'teacher' ) ) ) :
       echo '<ul class="teachers-list">';
       foreach( $teachers as $teacher ) :
         echo '<input type="checkbox" class="" id="teacher_' . $teacher->term_id . '" name="teacher_' . $teacher->term_id . '" /><label for="teacher_' . $teacher->term_id . '">' . $teacher->name . '</label>';
                             
        endforeach;
        echo '</ul>';
     endif;
   ?>
   </div>

   <input type="hidden" name="action" value="myfilter">
</form>

The PHP code for the AJAX filter in functions.php:

function mysite_filter_function(){

//groups checkboxes
if( $groups = get_terms( array( 'taxonomy' => 'group' ) ) ) :
$groups_terms = array();

foreach( $groups as $group ) {
    if( isset( $_POST['group_' . $group->term_id ] ) && $_POST['group_' . $group->term_id] == 'on' )
         $groups_terms[] = $group->slug;
}
endif;

//teachers checkboxes
if( $teachers = get_terms( array( 'taxonomy' => 'teacher' ) ) ) :
$teachers_terms = array();

foreach( $teachers as $teacher ) {
    if( isset( $_POST['teacher_' . $teacher->term_id ] ) && $_POST['teacher_' . $teacher->term_id] == 'on' )
         $teachers_terms[] = $teacher->slug;
}
endif;



if (empty($groups_terms) || empty($teachers_terms) ) {
 $relation = 'OR';
}else{
 $relation = 'AND';
}

$args = array(
    'orderby' => 'date',
    'post_type' => 'workshop',
    'posts_per_page' => -1,
    'tax_query' => array(
        'relation' => $relation,
        array(
            'taxonomy' => 'group',
            'field' => 'slug',
            'terms' => $groups_terms
        ),
        array(
            'taxonomy' => 'teacher',
            'field' => 'slug',
            'terms' => $teachers_terms
        )
    )
);

$query = new WP_Query( $args );

if( $query->have_posts() ) :
    while( $query->have_posts() ): $query->the_post();
        echo '<h2>' . $query->post->post_title . '</h2>';

    endwhile;
    wp_reset_postdata();
else :
    echo 'No posts found';
endif;

die();
}
add_action('wp_ajax_myfilter', 'mysite_filter_function');
add_action('wp_ajax_nopriv_myfilter', 'mysite_filter_function');

The JS code:

$('#filter').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;
});

Thanks!

2

What I would like to do is, when the user unselects all the terms in the filter it displays all the posts of my Custom Posts Type.

In that case, then make the tax query optional:

// In mysite_filter_function(), define $args like so:

$tax_query = array( 'relation' => 'AND' );

if ( ! empty( $groups_terms ) ) {
    $tax_query[] = array(
        'taxonomy' => 'group',
        'field'    => 'slug',
        'terms'    => $groups_terms,
    );
}

if ( ! empty( $teachers_terms ) ) {
    $tax_query[] = array(
        'taxonomy' => 'teacher',
        'field'    => 'slug',
        'terms'    => $teachers_terms,
    );
}

$args = array(
    'orderby'        => 'date',
    'post_type'      => 'workshop',
    'posts_per_page' => -1,
    'tax_query'      => $tax_query,
);
2
  • 1
    Thanks a lot @SallyCJ, it works like a charm. I understand now that "relation" was always active. It should be optional as you said. Thanks again! – Mathieu Préaud Feb 20 at 7:53
  • Yes - or more precisely, add the tax query clauses (i.e. do the $tax_query[] = array( ... );) only if the user selected/checked one or more terms in the relevant taxonomy. Sorry if I wasn't being clear.. 🙂 – Sally CJ Feb 20 at 8:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.