0

im using ajax to load more posts for custom post type using WP QUERY, now i'm having trouble hiding button if it's last post or if there are no posts left ( behaviour im getting is when i click it doesnt load post but it shows that there are no more posts, i want to avoid this, i want it to delete button on load before that so it doesnt reach that stage where user has to click button to be notified that there are no more posts Using paged is not an option. code i am using is:

JS:

 var $content = $('.content');
  var $loader = $('.loader');
  var ppp = 4;
  var offset = $content.find('.post').length;
  $loader.on('click', load_more);

  function load_more() {
    if (!($loader.hasClass('post_loading_loader') || $loader.hasClass('post_no_more_posts'))) {
      $.ajax({
        type: 'POST',
        dataType: 'html',
        url: ajax_object.ajaxurl,
        data: {
          'ppp': ppp,
          'offset': offset,
          'action': 'load_more'
        },
        beforeSend: function () {
          $loader.addClass('post_loading_loader').text('').append(' <i class="fas fa-spinner"></i>');

        },
        success: function (data) {
          var $result = $(data).filter('.post');
          var $data = $(data);
          if ($data.length) {

            var $newElements = $data.css({opacity: 0});
            $content.append($newElements);
            $newElements.animate({opacity: 1});
            $loader.removeClass('post_loading_loader').html(ajax_object.loadmore);
          } else {
            $loader.removeClass('post_loading_loader').addClass('post_no_more_posts').html(ajax_object.noposts);
          }
        },
        error: function (jqXHR, textStatus, errorThrown) {
          $loader.html($.parseJSON(jqXHR.responseText) + ' :: ' + textStatus + ' :: ' + errorThrown);
          console.log(jqXHR);
        },
      });
    }
    offset += ppp;
    return false;
  }

Functions.php:

add_action( 'wp_ajax_nopriv_load_more', 'load_more' );
add_action( 'wp_ajax_load_more', 'load_more' );
if ( ! function_exists( 'load_more' ) ) {
    function load_more() {
        $ppp    = ( isset( $_POST['ppp'] ) ) ? $_POST['ppp'] : 2;
        $offset = ( isset( $_POST['offset'] ) ) ? $_POST['offset'] : 0;

        $args = array(
            'post_type'      => 'toys',
            'posts_per_page' => $ppp,
            'offset'         => $offset
        ); ?>
        <?php
        $loop  = new WP_Query( $args );


        $out = '';
        if ( $loop->have_posts() ) :
            while ( $loop->have_posts() ) :
                $loop->the_post();
                $out .= include( get_template_directory() . '/views/partials/single-layout/toys.blade.php' );
            endwhile;
        endif;

        wp_reset_postdata();

        wp_die( $out );
    }
}
0

You can tell if the next request is not going to have any more posts if the previous request returned less posts than you asked for. So after retrieving the posts, count how many were returned. If it was less than ppp, then you can hide the load more button:

success: function ( data ) {
    var $data           = $( data );
    var $numberReturned = $data.find('.post').length;

    if ( $numberReturned > 0 ) {
        var $newElements = $data.css({opacity: 0});

        $content.append( $newElements );
        $newElements.animate({opacity: 1});
    }

    if ( $data.length == 0 || $numberReturned < ppp ) {
        $loader.addClass('post_no_more_posts').html(ajax_object.noposts);
    } else {
        $loader.removeClass('post_loading_loader').html(ajax_object.loadmore);
    }
},
  • This works most of the time, unless the last call fetches exactly the same number as they are requesting per page. Since he is fetching 4 at a time, that's not terribly unlikely. – tmdesigned Feb 11 at 11:41
  • That's what i was wondering too, and in each call it returns 4 if it has, so possibility of them overlapping is huge, tho it points me in good direction – Dzodzos Feb 11 at 15:17
0

You have to look ahead to know the total number of posts, then keep track of how many you have shown, so as to "predict" when you should no longer show the load more button.

Your PHP AJAX function could check each time, but you'd have to give it a way to send that information back (i.e. "no posts left after these ones") and it would have to check each time. I think it would make more sense and be more performant to just check once by providing yourself with an additional AJAX endpoint to know the number of posts.

add_action( 'wp_ajax_nopriv_so328351_num_posts', 'so328351_num_posts' );
add_action( 'wp_ajax_so328351_num_posts', 'so328351_num_posts' );

function so328351_num_posts() {

    $args = array(
        'post_type'      => 'toys',
        'posts_per_page' => -1
    ); 

    $loop  = new WP_Query( $args );

    $out = count( $loop );

    wp_reset_postdata();

    wp_die( $out );
}

Then at the beginning of your page's JavaScript, hit that endpoint to find out the number of posts you have.

    var totalPosts;

     $.ajax({
        type: 'POST',
        dataType: 'text',
        url: ajax_object.ajaxurl,
        data: {
          'action': 'so328351_num_posts'
        },
        success : function (data ){
            totalPosts = parseInt( data );
        },
        error: function (jqXHR, textStatus, errorThrown) {
          $loader.html($.parseJSON(jqXHR.responseText) + ' :: ' + textStatus + ' :: ' + errorThrown);
          console.log(jqXHR);
        });

Then, later, in your load_more function, you keep track of how many you've shown, and once you get there, you stop.

        success: function (data) {
          var $result = $(data).filter('.post');
          var $data = $(data);
          if ($data.length) {

            var $newElements = $data.css({opacity: 0});
            $content.append($newElements);
            $newElements.animate({opacity: 1});
            $loader.removeClass('post_loading_loader').html(ajax_object.loadmore);
          } 

          if ( offset + ppp >= totalPosts ){
   $loader.addClass('post_no_more_posts').html(ajax_object.noposts);
          }

So since we haven't yet added to our offset yet, we do it here. We are asking, "Does what we've shown so far, plus the number of posts we fetch each time (like we just did), go above our total number?" If so, we're done.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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