1

I built the ajax loader as follows.

How can I detect when it reaches the end of all posts? So that I can make the "More" button to disappear, or not clickable anymore.

In page template:

WP_Query stuff...

if ($press_posts->max_num_pages > 1) :
    echo '<a class="link-button" id="load-more">More</a>';
endif;

functions.php

function more_post_ajax() {
    $offset = $_POST["offset"];
    $ppp = $_POST["ppp"];
    header("Content-Type: text/html");

    $args = array(
        'cat' => 1,
        'posts_per_page' => $ppp,
        'offset' => $offset
    );

    $loop = new WP_Query($args);
    while ($loop->have_posts()) { $loop->the_post();
        get_template_part('template-parts/content', 'ajax');
    }
    exit;
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');

and javascripts:

<script>
    var ajaxUrl = "<?php echo admin_url('admin-ajax.php')?>";
    var page = 1;
    var ppp = 6; // posts per page

    jQuery("#load-more").on("click", function() {
        jQuery("#load-more").addClass("disabled");
        jQuery.post(ajaxUrl, {
            action: "more_post_ajax",
            offset: (page * ppp) + 1,
            ppp: ppp
        }).success(function(posts) {
            page++;
            jQuery("#press-listing").append(posts); // append to container
            jQuery("#load-more").removeClass("disabled");
        });

    });
</script>
  • Have you tried instead using the REST API posts endpoint? It includes headers that tell you how many pages there are and which page you're on – Tom J Nowell Aug 22 '18 at 20:51
  • @TomJNowell Thanks for the suggestion. But I don't have the knowledge for doing that at the moment. – Stickers Aug 22 '18 at 21:06
  • You could ask here? It's easier than what you're doing at the moment, I would also note that you should not be returning HTML and inserting it, you should be returning data then construction the template in JS – Tom J Nowell Aug 24 '18 at 20:38
  • @TomJNowell You're a moderator, you know that I can't ask without code. Can you point me to a right direction to get started quickly if possible? – Stickers Aug 31 '18 at 22:43
  • If you're just asking how to do something and don't have code you can just ask. It's when you already have code that has an issue that you need to post it so that others can understand what's going on or spot things you might have missed – Tom J Nowell Sep 1 '18 at 0:07
2

Page template:

<div class="entry-content">
    <?php 
        $args = array(
            'post_type' => 'post',
            'post_status' => 'publish',
            'posts_per_page' => '2',
            'paged' => 1,
        );
        $my_posts = new WP_Query($args);
        if ($my_posts->have_posts()) : 
    ?>
        <div class="my-posts">
            <?php while ($my_posts->have_posts()) : $my_posts->the_post(); ?>
                <h2><?php the_title(); ?></h2>
                <?php the_excerpt(); ?>
            <?php endwhile; ?>
        </div>
    <?php endif; ?>
    <div class="loadmore">Load More...</div>
</div>

Ajax jQuery (Load more button):

<script type="text/javascript">
var ajaxurl = "<?php echo admin_url('admin-ajax.php'); ?>";
var page = 2;
jQuery(function($) {
    $('body').on('click', '.loadmore', function() {
        var data = {
            'action': 'load_posts_by_ajax',
            'page': page,
            'security': '<?php echo wp_create_nonce("load_more_posts"); ?>'
        };

        max = <?php echo $my_posts->max_num_pages; ?>

        $.post(ajaxurl, data, function(response) {
            $('.my-posts').append(response);
            if (page < max) {
                // end of posts
            }
            page++;
        });
    });
});
</script>

Functions:

function load_posts_by_ajax_callback() {
    check_ajax_referer('load_more_posts', 'security');
    $paged = $_POST['page'];
    $args = array(
        'post_type' => 'post',
        'post_status' => 'publish',
        'posts_per_page' => '2',
        'paged' => $paged,
   );
    $my_posts = new WP_Query($args);
    if ($my_posts->have_posts()) :
        ?>
        <?php while ($my_posts->have_posts()) : $my_posts->the_post(); ?>
            <h2><?php the_title(); ?></h2>
            <?php the_excerpt(); ?>
        <?php endwhile; ?>
        <?php
    endif;
    wp_die();
}
add_action('wp_ajax_load_posts_by_ajax', 'load_posts_by_ajax_callback');
add_action('wp_ajax_nopriv_load_posts_by_ajax', 'load_posts_by_ajax_callback');

Addition - Ajax jQuery (Load on scroll):

$(window).scroll(function() {
    if ($(window).scrollTop() == $(document).height() - $(window).height()) {
        var data = {
            'action': 'load_posts_by_ajax',
            'page': page,
            'security': '<?php echo wp_create_nonce("load_more_posts"); ?>'
        };

        $.post(ajaxurl, data, function(response) {
            $('.my-posts').append(response);
            page++;
        });
    }
});

Source

0

I agree with the commenter @TomJNowell it could worth looking into the REST API. However, regarding your specific question:

Here's an idea:

  • Check if there are any posts remaining in your more_post_ajax() function and include that in your response in addition to the posts you're sending back. For example, you could have a more_posts boolean flag, or perhaps a count; however you'd like to do it.
  • On the js end of things, expand the implementation of .success(function(posts) { ... }) to add logic that handles this new piece of information in the response. If no posts are remaining, you could disable/hide your #load-more element and perhaps add a message to the user that no posts are remaining.

I'm not sure what exactly is in the template part that you call via get_template_part('template-parts/content', 'ajax') or what its doing so its hard to be more specific regarding that area.

Either way, your instance of WP_Query stored in $loop has a posts property that's an array of your posts. I could assume you want to send the posts back as part of your response.

The WP_Query property found_posts is a count of all posts that match your criteria without consideration of your offset (i.e. its total count of posts), unless this is disabled with the arg no_found_rows (N/A in this case). Since you know your posts per page and offset you have the information to pass back in your response if there are more posts available to load or not. Another way could be the max_num_pages property.

You could combine these into an array/object and use wp_send_json() or wp_send_json_success() to send them and then process the response in js. You would need jQuery's parseJSON() to parse the response.

If you're really married to what your template partial is outputting and liking how you are easily doing jQuery("#press-listing").append(posts) on the js side to display it, you could capture the output of get_template_part('template-parts/content', 'ajax'); using output buffering (a little dirty) to collect it for including in your response, e.g.

ob_start();
get_template_part('template-parts/content', 'ajax');
// call ob_get_contents() and load the return value into an array or string to send back
ob_end_clean();
0

Change in your code $offet to $paged variable WP_Query can keep track of the pages that will give you the total number of pages in your loop object as

$loop->max_num_pages

<script>
    var ajaxUrl = "<?php echo admin_url('admin-ajax.php')?>";
    var page = 1;
    var ppp = 6; // posts per page

    jQuery("#load-more").on("click", function() {
        jQuery("#load-more").addClass("disabled");
        jQuery.post(ajaxUrl, {
            action: "more_post_ajax",
            page: page,
            ppp: ppp
        }).success(function(posts) {
            // execute this block only if there is post
            if(posts) { 
            page++;
            jQuery("#press-listing").append(posts); // append to container
            jQuery("#load-more").removeClass("disabled");
            }
        });

    });
</script>

And you php ajax function would be

function more_post_ajax() {
    $page = $_POST["page"];
    $ppp = $_POST["ppp"];
    header("Content-Type: text/html");

    $args = array(
        'cat' => 1,
        'posts_per_page' => $ppp,
        'paged' => $page
    );

    $loop = new WP_Query($args);

    if($loop->max_num_pages <= $page):

    while ($loop->have_posts()) { $loop->the_post();
        get_template_part('template-parts/content', 'ajax');
    }
    exit;

   else:
     echo 0;
     die();

   endif;
}
add_action('wp_ajax_nopriv_more_post_ajax', 'more_post_ajax');
add_action('wp_ajax_more_post_ajax', 'more_post_ajax');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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