Skip Navigation

[Resolved] Taxonomy Archives for Product Categories with AJAX – change posts per page

This support ticket is created 4 years, 2 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

No supporters are available to work today on Toolset forum. Feel free to create tickets and we will handle it as soon as we are online. Thank you for your understanding.

Sun Mon Tue Wed Thu Fri Sat
9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 - - 9:00 – 13:00
14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 - - 14:00 – 18:00

Supporter timezone: Africa/Casablanca (GMT+01:00)

This topic contains 18 replies, has 2 voices.

Last updated by umbertoZ 4 years, 2 months ago.

Assisted by: Jamal.

Author
Posts
#1795987

I think I have used my shots, I can't provide any additional code without testing it, otherwise, we'll still be hitting the same wall.

I activated a private reply for you, please add FTP access and I'll check how the code is behaving at the server level. I can't test the custom code without having FTP access. I might make a typo error that will crash the site.

#1796727

I think that we were not handling this problem in the right way. We first tried to handle the reload page by relying on $_GET. And then we tried to handle the AJAX case. I believe we should handle the AJAX way first, and then we may find a way for the page reload case.

I discussed this with the team and run a test locally and I believe we found a way to get to what you want.

The solution relies on a hidden field inside the filters that will hold the number of posts per page, a shortcode that will get the number posts per page, and finally the hook into the query to change its number of posts per page.

First, we added a hidden field inside the filters and we named it "pager", then we added a special class to it "js-wpv-filter-trigger", which will let Toolset integrate the value of the hidden field into the AJAX call form data.

We then created a custom shortcode to get the "number of posts per page" from the AJAX form data or from the $_GET object.

add_shortcode('pager', 'my_pager_func');
function my_pager_func(){
  $default_pager = 2;
  if ( wp_doing_ajax() ) {
    $filters = $_POST['search']['dps_general'];
    foreach( $filters as $filter ) {
      if ( $filter['name'] == 'pager' ) return (int) $filter['value'];
    }
    return $default_pager;
    return print_r( $filters, true);
  } else {
    return isset( $_GET['pager'] ) ? (int) $_GET['pager'] : $default_pager;
  }
}

We use this shortcode to populate the value of the hidden field:

<input type="hidden" name="pager" value=[pager] class="js-wpv-filter-trigger" />

Please not that the shortcode is not wrapped in single or double quotes

Then we can use it, and its function "my_pager_func" inside of our hook:

add_filter('pre_get_posts','func_include_child_terms',999);
function func_include_child_terms( $query ) {
  if ( $query->is_main_query() and  $query->is_tax( 'product_cat' ) ) {
    $pager = my_pager_func();
    if ( $pager > 0 ) {
      $query->set( 'posts_per_page', $pager );
    }
  }
  return $query;
}

Please note that we do not rely on is_admin() as it will always return true for AJAX calls

Bonus
By implementing this solution, we can integrate the buttons for the number of posts per page directly into our view without having to fully reload the page. It will require custom Javascript code that will prevent the page from reloading, takes the value of the number of posts per page, enters it into the hidden field, then triggering a change on a filter so the view will trigger an AJAX reload.
Check this pseudo code:

jQuery('.per-page a').off('click').on('click', function(event){
  event.preventDefault();
  var link = jQuery(this);
  var nposts = link.data('pager');
  var pager = jQuery('input[name="pager"]');
  pager.val(nposts);
  jQuery('#pa_brand-airav').trigger('change')
})

This code needs to be run at the first-page load and after each AJAX call, especially, when the search is performed or when pagination completes.
The complete Javascript code is:

function ajax_reload_with_pager(){
  jQuery('.per-page a').off('click').on('click', function(event){
    event.preventDefault();
    var link = jQuery(this);
    var nposts = link.data('pager');
    var pager = jQuery('input[name="pager"]');
    pager.val(nposts);
    jQuery('#pa_brand-airav').trigger('change');
  })
}

// execute code when the page loads
jQuery(function(){
  ajax_reload_with_pager();
})

// when pagination completes.
jQuery( document ).on( 'js_event_wpv_pagination_completed', function( event, data ) {
  ajax_reload_with_pager();
});

// when search results are loaded
jQuery( document ).on( 'js_event_wpv_parametric_search_results_updated', function( event, data ) {
  ajax_reload_with_pager();
});

I already implemented this for you. Please test your archive page and let me know if we missed something.

#1796763

Wow!!! You made an extraordinary great job!!

I'm very imrpessed by the quality and dedication of your support.

My issue is resolved now. Thank you very much!

#1802843

Hi Jamal, I've built a Product View that works just like the archive page (same filters, same pagination...). I would like to activate the "per-page" buttons just like on the archive page, but I found the custom code doesn't work here.

I tried to add a condition on func_include_child_terms:

add_filter('pre_get_posts','func_include_child_terms',999);
function func_include_child_terms( $query ) {
  if ( ( $query->is_main_query() && $query->is_tax( 'product_cat' ) ) || ( $query->is_main_query() && is_page(14053) ) ) {

but it doesn't work. Can you help me again?

cheers