I made a code for woocommerce product listings with ajax load more by scroll and ajax filters by category – all works great, but there is one case, when it didn’t. Only on the main shop page when I select two or more categories in filter after I get first set of products and try to scroll down to start loading I get nothing more – it send ajax request and get no result – the same action on category listing works great. Filtering by single category works great on both pages. Below is the php code called by ajax load more request, maybe you can help me with this, after two days I have no more idea how to fix that.
function mev_load_more_products() {
$args = json_decode(stripslashes($_POST['query']), true);
$args['paged'] = $_POST['page'] + 1;
$args['post_status'] = 'publish';
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
get_template_part('woocommerce/content', 'product');
}
}
die();
}
add_action('wp_ajax_load_more_products', 'mev_load_more_products');
add_action('wp_ajax_nopriv_load_more_products', 'mev_load_more_products');
And this is JS code sending request to this action:
let currentPage = catalog_params.current_page;
let queryVars = catalog_params.query_vars;
const productList = $('.catalog-page-list');
$(window).scroll(function () {
if ($(document).scrollTop() > ($(document).height() - 2000)) {
let data = {
'action' : 'load_more_products',
'query' : queryVars,
'page' : currentPage
};
$.ajax({
url: woocommerce_params.ajax_url,
data: data,
method: 'POST',
success: function(data) {
if (data) {
productList.find('.product-card:last-of-type').after(data);
currentPage++;
}
}
});
}
});
This is JS code filtering products list using data from form:
const defaultQueryVars = catalog_params.query_vars;
let formData = $('#catalog-filters').serializeArray();
let filterData = {
'action' : 'filter_products',
'filters' : {},
'query' : defaultQueryVars
};
formData.forEach(item => {
if (item.name.endsWith('[]')) {
if (!filterData.filters[item.name]) {
filterData.filters[item.name] = [];
}
filterData.filters[item.name].push(item.value);
} else {
filterData.filters[item.name] = item.value;
}
});
$.ajax({
url: woocommerce_params.ajax_url,
data: filterData,
method: 'POST',
success: function(data) {
productList.html(data.html);
currentPage = 1;
queryVars = data.query_vars;
}
});
And action for filtering:
function mev_filter_products() {
$args = json_decode(stripslashes($_POST['query']), true);
$args['paged'] = 1;
if (isset($_POST['filters'])) {
$filters = $_POST['filters'];
if (!isset($args['tax_query'])) {
$args['tax_query'] = [];
}
if (isset($filters['category'])) {
$args['tax_query'][] = [
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $filters['category'],
'operator' => 'IN',
];
}
}
$query = new WP_Query($args);
ob_start();
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
get_template_part('woocommerce/content', 'product');
}
}
$html = ob_get_clean();
ob_end_clean();
wp_send_json([
'query_vars' => json_encode($query->query_vars),
'html' => $html,
]);
die();
}
add_action('wp_ajax_filter_products', 'mev_filter_products');
add_action('wp_ajax_nopriv_filter_products', 'mev_filter_products');
As I mentioned it all works great if I open product category page, but for main shop page works only if I do not choose two categories in filters.
For complete this is how I load JS file with params:
wp_register_script('kp-product-catalog', get_template_directory_uri() . '/js/product-catalog.js', ['jquery', 'woocommerce'], time(), true );
if (is_shop() || is_product_category() || is_product_tag() || is_tax('seria') || is_tax('product_brand')) {
global $wp_query;
wp_localize_script( 'kp-product-catalog', 'catalog_params', array(
'query_vars' => json_encode($wp_query->query_vars),
'current_page' => get_query_var('paged') ? get_query_var('paged') : 1,
));
wp_enqueue_script('kp-product-catalog');
}