$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>wp query - WP_Query ajax loader detect end of posts|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

wp query - WP_Query ajax loader detect end of posts

matteradmin10PV0评论

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>

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>
Share Improve this question asked Aug 22, 2018 at 20:27 StickersStickers 2521 gold badge6 silver badges17 bronze badges 5
  • 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 Commented Aug 22, 2018 at 20:51
  • @TomJNowell Thanks for the suggestion. But I don't have the knowledge for doing that at the moment. – Stickers Commented Aug 22, 2018 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 Commented Aug 24, 2018 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 Commented Aug 31, 2018 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 Commented Sep 1, 2018 at 0:07
Add a comment  | 

3 Answers 3

Reset to default 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

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();

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');
Post a comment

comment list (0)

  1. No comments so far