Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Filter WordPress posts by multiple custom taxonomy terms with AJAX Raw
<?php
/**
* AJAC filter posts by taxonomy term
*/
function vb_filter_posts_mt() {
if( !isset( $_POST['nonce'] ) || !wp_verify_nonce( $_POST['nonce'], 'bobz' ) )
die('Permission denied');
/**
* Default response
*/
$response = [
'status' => 500,
'message' => 'Something is wrong, please try again later ...',
'content' => false,
'found' => 0
];
$all = false;
$terms = $_POST['params']['terms'];
$page = intval($_POST['params']['page']);
$qty = intval($_POST['params']['qty']);
$pager = isset($_POST['pager']) ? $_POST['pager'] : 'pager';
$tax_qry = [];
$msg = '';
/**
* Check if term exists
*/
if (!is_array($terms)) :
$response = [
'status' => 501,
'message' => 'Term doesn\'t exist',
'content' => 0
];
die(json_encode($response));
else :
foreach ($terms as $tax => $slugs) :
if (in_array('all-terms', $slugs)) {
$all = true;
}
$tax_qry[] = [
'taxonomy' => $tax,
'field' => 'slug',
'terms' => $slugs,
];
endforeach;
endif;
/**
* Setup query
*/
$args = [
'paged' => $page,
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => $qty,
];
if ($tax_qry && !$all) :
$args['tax_query'] = $tax_qry;
endif;
$qry = new WP_Query($args);
ob_start();
if ($qry->have_posts()) :
while ($qry->have_posts()) : $qry->the_post(); ?>
<article class="loop-item">
<header>
<h2 class="entry-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
</header>
<div class="entry-summary">
<?php the_excerpt(); ?>
</div>
</article>
<?php endwhile;
/**
* Pagination
*/
if ( $pager == 'pager' )
vb_mt_ajax_pager($qry,$page);
foreach ($tax_qry as $tax) :
$msg .= 'Displaying terms: ';
foreach ($tax['terms'] as $trm) :
$msg .= $trm . ', ';
endforeach;
$msg .= ' from taxonomy: ' . $tax['taxonomy'];
$msg .= '. Found: ' . $qry->found_posts . ' posts';
endforeach;
$response = [
'status' => 200,
'found' => $qry->found_posts,
'message' => $msg,
'method' => $pager,
'next' => $page + 1
];
else :
$response = [
'status' => 201,
'message' => 'No posts found',
'next' => 0
];
endif;
$response['content'] = ob_get_clean();
die(json_encode($response));
}
add_action('wp_ajax_do_filter_posts_mt', 'vb_filter_posts_mt');
add_action('wp_ajax_nopriv_do_filter_posts_mt', 'vb_filter_posts_mt');
/**
* Shortocde for displaying terms filter and results on page
*/
function vb_filter_posts_mt_sc($atts) {
$a = shortcode_atts( array(
'tax' => 'post_tag', // Taxonomy
'terms' => false, // Get specific taxonomy terms only
'active' => false, // Set active term by ID
'per_page' => 12, // How many posts per page,
'pager' => 'pager' // 'pager' to use numbered pagination || 'infscr' to use infinite scroll
), $atts );
$result = NULL;
$terms = get_terms($a['tax']);
if (count($terms)) :
ob_start(); ?>
<div id="container-async" data-paged="<?= $a['per_page']; ?>" class="sc-ajax-filter sc-ajax-filter-multi">
<ul class="nav-filter">
<li>
<a href="#" data-filter="<?= $terms[0]->taxonomy; ?>" data-term="all-terms" data-page="1">
Show All
</a>
</li>
<?php foreach ($terms as $term) : ?>
<li<?php if ($term->term_id == $a['active']) :?> class="active"<?php endif; ?>>
<a href="<?= get_term_link( $term, $term->taxonomy ); ?>" data-filter="<?= $term->taxonomy; ?>" data-term="<?= $term->slug; ?>" data-page="1">
<?= $term->name; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<div class="status"></div>
<div class="content"></div>
<?php if ( $a['pager'] == 'infscr' ) : ?>
<nav class="pagination infscr-pager">
<a href="#page-2" class="btn btn-primary">Load More</a>
</nav>
<?php endif; ?>
</div>
<?php $result = ob_get_clean();
endif;
return $result;
}
add_shortcode( 'ajax_filter_posts_mt', 'vb_filter_posts_mt_sc');
/**
* Pagination
*/
function vb_mt_ajax_pager( $query = null, $paged = 1 ) {
if (!$query)
return;
$paginate = paginate_links([
'base' => '%_%',
'type' => 'array',
'total' => $query->max_num_pages,
'format' => '#page=%#%',
'current' => max( 1, $paged ),
'prev_text' => 'Prev',
'next_text' => 'Next'
]);
if ($query->max_num_pages > 1) : ?>
<ul class="pagination">
<?php foreach ( $paginate as $page ) :?>
<li><?php echo $page; ?></li>
<?php endforeach; ?>
</ul>
<?php endif;
}
@tanmaypatel86
Copy link

tanmaypatel86 commented Mar 19, 2020

<nav class="pagination infscr-pager">
    <a href="#page-2" class="btn btn-primary">Load More</a>
</nav>

Can you please help me for dynamic next page number in above code for load more posts like #page-2
If you can make this below posts with "load more" or "infinite scroll" then it is huge advantage for all developers
https://www.bobz.co/filter-wordpress-posts-by-custom-taxonomy-term-with-ajax-and-pagination

@Bobz-zg
Copy link
Author

Bobz-zg commented Mar 31, 2020

@tanmaypatel86 what exactly is the problem you are facing?

@tanmaypatel86
Copy link

tanmaypatel86 commented Mar 31, 2020

I have used your code of infinite scrolling with specific instructions but in my last message, you can see "#page-2" so how can I do this number as dynamic in pagination of infinite scrolling. so please help me. I love your all codes.

@Bobz-zg
Copy link
Author

Bobz-zg commented Mar 31, 2020

@tanmaypatel86 so what you want to do is to check 'on scroll' event if pagination button is in view (is it visible on screen right now) and trigger click on that item.
This will give you same result like you scroll down and click the button yourself manually.
You also might want to trigger load more eg 200-300px before it comes into view, just because it takes some time for content to load.

1. check if pagination element 'infscr-pager' is in view
https://stackoverflow.com/questions/123999/how-can-i-tell-if-a-dom-element-is-visible-in-the-current-viewport

Be sure to attach this to a 'scroll' event, meaning check should be fired while user is scrolling.
Another thing to note is that you want to 'debounce', this means while user is scrolling you will not fire your 'isInView' function all the time, but eg every 200ms, so you will reduce how many times you call a function which is more optimised way so you don't overload and kill the browser.

You can find out more here:
https://stackoverflow.com/questions/36415992/debounce-jquery-scroll-events

2. trigger click on element 'infscr-pager a'
https://stackoverflow.com/questions/5811122/how-to-trigger-a-click-on-a-link-using-jquery

Hope that helps. Happy coding and stay safe

@tanmaypatel86
Copy link

tanmaypatel86 commented Mar 31, 2020

https://www.bobz.co/filter-wordpress-posts-by-custom-taxonomy-term-with-ajax-and-pagination

You can see you have wrote this below code for load more pagination,

<?php if ( $a['pager'] == 'infscr' ) : ?>
			<nav class="pagination infscr-pager">
				<a href="#page-2" class="btn btn-primary">Load More</a>
			</nav>
		<?php endif; ?>

I above code, in href you have wrote static "2" as "#page-2" I want to dynamic number same as like normal pagination when I tried your code, it's working with page 2 but then after I got this error message like page number is undefined.

So I request you to help me how can I make this number as dynaminc "#page-2" in <a href="#page-2" class="btn btn-primary">Load More</a>

@tanmaypatel86
Copy link

tanmaypatel86 commented Mar 31, 2020

If you can create below your post as "Load More" pagination then It is very thankful for all developer
https://www.bobz.co/filter-wordpress-posts-by-custom-taxonomy-term-with-ajax-and-pagination

@Bobz-zg
Copy link
Author

Bobz-zg commented Mar 31, 2020

There is a different post with few minor modifications:
https://www.bobz.co/filter-wordpress-posts-multiple-taxonomy-terms-ajax-pagination
https://www.bobz.co/blog/demo-filter-wordpress-posts-multiple-taxonomy-terms-ajax-infinite-scroll

  1. static href="page-2" is in shortcode only, this is the code that's generated when you open page for first time.
    Next page is always 2, if you just opend the page because you start at page 1, click opens page 2.
    That's why it's static, there is no need to be dynamic here.

If it says undefined, it means you did not select element.
Problem is in Javascript you are not updating page number https://gist.github.com/Bobz-zg/8bc7c5a99a1ab6ee969a16004c0403d5
Check Line 59, this is dynamically updating "page-{next-number}"

@tanmaypatel86
Copy link

tanmaypatel86 commented Mar 31, 2020

I have set all codes for "Load more" pagination and it's working. Awesome. I am very thankful to you for guiding me and posts your code as permium.

Just need help on minor one query. when I click on load more button again again and when I reach button like this "You reached the end". You can see status "Posts found: undefined" so How can display total posts number here. if you can help then it's good for me.
http://prntscr.com/rpxlwb

@Bobz-zg
Copy link
Author

Bobz-zg commented Mar 31, 2020

@tanmaypatel86 I'm very happy that you managed to come up with solution on your own.
Usually people are looking for copy/paste solutions but that doesn't make them developers, kudos to you, very good job :)

I'm not sure which code are you using, if it's this: https://gist.github.com/Bobz-zg/8bc7c5a99a1ab6ee969a16004c0403d5
L73 : $status.html(data.message); is adding content to that status div (maybe data.message does not exist)
L96 : $status.html(msg); is also adding content to same status div

Tbh, looks like there is something wrong in my code there, not sure is complete needed and why I have added that at the first place.
Be sure to inspect what data is returned back, just console log or look in network panel for admin-ajax.php under XHR tab

@tanmaypatel86
Copy link

tanmaypatel86 commented Mar 31, 2020

Thank you for your message. I will try to fix it using console log.

I have used this below code for that,

msg = textStatus;
if (textStatus === 'success') {
    msg = data.responseJSON.found;
}
$status.text('Posts found: ' + msg);

@tanmaypatel86
Copy link

tanmaypatel86 commented Apr 6, 2020

I have also fixed it the issue of "Posts found: undefined" (when I click on load more button again again and when I reach button like this "You reached the end"). Thank you so much for amazing coding.

@Bobz-zg
Copy link
Author

Bobz-zg commented Apr 7, 2020

@tanmaypatel86 glad to hear that, good work!

@tanmaypatel86
Copy link

tanmaypatel86 commented Apr 8, 2020

Thank you :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment