Answer the question
In order to leave comments, you need to log in
How to correctly form pagination when loading posts with AJAX?
Hello. There is a product page.
On the left are the filtering options (by price and by size).
When choosing a size or changing prices, a request is made to load posts. In the AJAX callback (in functions.php) this data is received and passed to WP_Query to load the posts (of the right size and within the selected price range). After receiving the posts back, we send the markup of the posts along with the pagination.
The filter works as it should, but pagination links are formed incorrectly.
1. If you just go to the product page (without applying filters), then in pagination there are such links:
http:// example .com/page/page_number/
2. If you apply a filter (load new markup) in the links, these are the addresses (I use GET request):
http:// example .com/wp-admin/admin-ajax.php?action=my_ajax_action&minPrice=3000&maxPrice=20000&sizes[]=216&paged=page_number
And nothing works when navigating through them.
3. I need something like:
http:// example .com/page/page_number/?minPrice=3000&maxPrice=20000&sizes[]=216
Attention. I don't want the posts to be loaded by AJAX when clicking on the pagination links. When you click on the link, the page will simply reload and the products of the selected page will be displayed with the filter applied.
Code with comments.
script.js:
// функция отправляет запрос на подгрузку нужных товаров
// вызывается, когда пользователь меняет диапазон цен или выбирает размер товара
function updateProducts(minPrice, maxPrice, sizes) {
$.ajax({
url: ajaxurl,
type: "GET",
data: {
action: 'my_ajax_action',
minPrice: minPrice,
maxPrice: maxPrice,
sizes: sizes,
},
success: function (html) {
const shop = document.querySelector(".shop-catalog"); // элемент с постами и пагинацией
shop.innerHTML = html; // полученную разметку помещаем заместо старых постов и старой пагинации
}
});
}
add_action("wp_ajax_my_ajax_action", "filter_products");
add_action("wp_ajax_nopriv_my_ajax_action", "filter_products");
function filter_products() {
$minPrice = $_GET['minPrice'];
$maxPrice = $_GET['maxPrice'];
$sizes = $_GET['sizes'];
$query = new WP_Query([
'post_type' => 'product',
'paged' => 1, // пока что 1, потом буду подставлять нужную страницу
'posts_per_page' => 15,
'orderby' => 'date',
'order' => 'DESC',
// получаем товары с ценами от minPrice до maxPrice
'meta_query' => [
[
'key' => '_price',
'value' => [$minPrice, $maxPrice],
'compare' => 'BETWEEN',
'type' => 'NUMERIC'
],
],
// с атрибутами (размерами), указанными в массиве $sizes
'tax_query' => [
[
'taxonomy' => 'pa_размер',
'field' => 'id',
'terms' => $sizes,
]
]
]);
// пришлось вызывать это, т. к. без этого не формировалась пагинация, т. к. wc_get_loop_prop('total') не возвращал правильное значение и цикл внизу не запускался
wc_setup_loop([
'current_page' => 1,
'total' => $query->found_posts,
'total_pages' => $query->max_num_pages,
'per_page' => $query->post_count,
]);
// этот код вырван из archive-product.php, чтобы товары посты выводились точно также как там (как на странице товара, когда заходим в первый раз)
if ($query->have_posts()) {
woocommerce_product_loop_start(); // <ul>
if (wc_get_loop_prop('total')) {
while ($query->have_posts()) {
$query->the_post();
do_action('woocommerce_shop_loop'); // не помню, да и не особо важно, что это
wc_get_template_part('content', 'product'); // сам товар
}
}
wp_reset_postdata();
woocommerce_product_loop_end(); // </ul>
do_action('woocommerce_after_shop_loop'); // сама пагинация, ниже оставлю код
} else {
do_action('woocommerce_no_products_found');
}
wp_die();
}
$total = isset( $total ) ? $total : wc_get_loop_prop( 'total_pages' );
$current = isset( $current ) ? $current : wc_get_loop_prop( 'current_page' );
$base = isset( $base ) ? $base : esc_url_raw( str_replace( 999999999, '%#%', remove_query_arg( 'add-to-cart', get_pagenum_link( 999999999, false ) ) ) );
$format = isset( $format ) ? $format : '';
if ( $total <= 1 ) {
return;
}
?>
<nav class="woocommerce-pagination">
<?php
echo paginate_links(
apply_filters(
'woocommerce_pagination_args',
array( // WPCS: XSS ok.
'base' => $base,
'format' => $format,
'add_args' => false,
'current' => max( 1, $current ),
'total' => $total,
'prev_text' => is_rtl() ? '→' : '←',
'next_text' => is_rtl() ? '←' : '→',
'type' => 'list',
'end_size' => 3,
'mid_size' => 3,
)
)
);
?>
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question