WP_Query with ajax handler returns the same posts

I have a problem that is getting me bald atm. I have a ajax call that handles a loop that handles some querys and returns posts for me.

So far so good, but the first time the user sees the page we should load 10 posts, and then we want to click a button to request 5 more.

Read More

So far so good.

But when we request the 5 more posts we get the 5 first posts again.

My batchloop

<?php   
// Our include  
define('WP_USE_THEMES', false);  
require_once('../../../wp-load.php');  

// Our variables  
$posts = (isset($_GET['numPosts'])) ? $_GET['numPosts'] : 0;  
$page = (isset($_GET['pageNumber'])) ? $_GET['pageNumber'] : 0;  
$category = (isset($_GET['category_name'])) ? $_GET['category_name'] : 0;  

var_dump($posts);

$args = array(  
    'posts_per_page' => $posts,
    'category_name'  => $category, 
    'post_status'    => 'publish',
    'orderby'        => 'date',
    'order'          => 'DESC',
    'paged'          => $page 
);

query_posts($args);  

// $query = new WP_query($args);

// our loop  
if (have_posts()) {  

    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; query_posts($args);

       while (have_posts()){  
              the_post();  

              get_template_part( 'thumbs', get_post_format() );  
       }  
} 

// unset($page, $posts, $category);

// wp_reset_postdata();
wp_reset_query();
?> 

Does anybody sees what im doing wrong?

EDIT:

batch handler

 function _batchhandler() { 
        var getamount = localStorage.getItem('amount'); 

        console.log('amount of posts to retrive ' + JSON.parse(getamount));

        // Ajax call
        $.ajax({
            type: 'GET',
            data: {
                posts: getamount, 
                page: page,
                category: 'work'
            },
            dataType: 'html',
            url: 'http://dev.xxx.se/wp-content/themes/xxx/batch.php',
            beforeSend: function() {
                _setHeader;
                if( page != 1 ) {
                    console.log('Loading');
                    // Show the preloader
                    $('body').prepend('<div class="preloader"><span class="rotate"></span></div>');
                }
                // If we reach the end we hide the show more button
                if( page >= total ) {
                    $('.load').hide();
                }
            },
            success: function(data) {
                console.log(page);  
                var scroll = ($('.thumb').height() * posts);
                // If thumbs exist append them
                if( data.length ) { 
                    // Append the data
                    $('#batch').append(data);

                    // Remove the crappy width and height attrs from the image * Generated by WP *
                    $('img').removeAttr('height').removeAttr('width');

                    // Animate each new object in a nice way
                    (function _showitem() {
                        $('#batch .thumb:hidden:first').addClass('show', 80, _showitem);

                        // On the last request do load any more
                        loading = false;  
                    })();

                    // Remove the preloader
                    $('.preloader').fadeOut(200, function() {
                        $('.preloader').remove();   
                    });
                }
                // return false;
            },
            complete: function() {
                // Delete storage
                localStorage.clear();

                // Update the scroller to match the updated content length
                if (scroller)
                    setTimeout("scroller.refresh()", 300);

                // Initalize the load more button
                _clickhandler();
            },
            error: function() {
                console.log('No page found');
            }
        });
    }

and my load more button function

 $('.load').on('click', function(event) {
            event.preventDefault(); 
            // Delete storage
            localStorage.clear();

            if(!loading) {
                loading = true;
                // Increase our pagenumber per click
                page++;
                count++;
                // Remove preloader
                $('.preloader').remove();

                setTimeout(function() {
                    $('#batch').css({
                        '-webkit-transform' : 'translateY(-' + ($('#batch li').outerHeight() * count)  + 'px)'
                    });
                }, 30);

                // Clear storage and set a new
                localStorage.setItem('amount', JSON.stringify(amount.medium));
                var getamount = localStorage.getItem('amount');

                // Send the request to the handler                  
                _batchhandler(page);    
            }      

        });

Everything seems fine, the first 10 (1-10) posts loads as the should, but the first time “load more” is clicked we get the next 5 results but the results are posts that loaded the first time (5-10). If we click the “load more” again, we get the correct result

Related posts

Leave a Reply

1 comment

  1. Caveat, I can’t really test this right now. However, there are several things that I think could be improved from your code.

    First if we read the codex or some tips on using ajax we can setup an ajax callback function that isn’t pointing to a file where we have to bootstrap the WordPress load functions.

    I will make the assumption that all your script is in a JS file and being properly enqueued:

    // embed the javascript file that makes the AJAX request
    wp_enqueue_script( 'wpa-95258-ajax-request', plugin_dir_url( __FILE__ ) . 'js/ajax.js', array( 'jquery' ) );
    
    // declare the URL to the file that handles the AJAX request (wp-admin/admin-ajax.php)
    wp_localize_script( 'wpa-95258-ajax-request', 'wpa-95258-ajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
    

    Using wp_localize_script we can pass some variables to a script object that will then be available in the script. We’ll use this for the .ajax URL parameter. We also need an action parameter, because WordPress will look for

    // this hook is fired if the current viewer is not logged in
    do_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] );
    
    // if logged in:
    do_action( 'wp_ajax_' . $_POST['action'] );
    

    So we can use that later on to attach a callback function to any ajax action. First I’ve adapted your .ajax to have an action and use the WordPress ajax url:

    function _batchhandler() { 
        var getamount = localStorage.getItem('amount'); 
    
        console.log('amount of posts to retrive ' + JSON.parse(getamount));
    
        // Ajax call
        $.ajax({
            type: 'GET',
            data: {
                posts: getamount, 
                page: page,
                category: 'work',
                action: 'batchhandler' // use this to add a callback
            },
            dataType: 'html',
            url: wpa-95258-ajax.ajaxurl, //from localize script
            beforeSend: function() {
                _setHeader;
                if( page != 1 ) {
                    console.log('Loading');
                    // Show the preloader
                    $('body').prepend('<div class="preloader"><span class="rotate"></span></div>');
                }
                // If we reach the end we hide the show more button
                if( page >= total ) {
                    $('.load').hide();
                }
            },
            success: function(data) {
                console.log(page);  
                var scroll = ($('.thumb').height() * posts);
                // If thumbs exist append them
                if( data.length ) { 
                    // Append the data
                    $('#batch').append(data);
    
                    // Remove the crappy width and height attrs from the image * Generated by WP *
                    $('img').removeAttr('height').removeAttr('width');
    
                    // Animate each new object in a nice way
                    (function _showitem() {
                        $('#batch .thumb:hidden:first').addClass('show', 80, _showitem);
    
                        // On the last request do load any more
                        loading = false;  
                    })();
    
                    // Remove the preloader
                    $('.preloader').fadeOut(200, function() {
                        $('.preloader').remove();   
                    });
                }
                // return false;
            },
            complete: function() {
                // Delete storage
                localStorage.clear();
    
                // Update the scroller to match the updated content length
                if (scroller)
                    setTimeout("scroller.refresh()", 300);
    
                // Initalize the load more button
                _clickhandler();
            },
            error: function() {
                console.log('No page found');
            }
        });
    }
    

    Now that we have a hook to attach to we can build the callback function without the bootstrapped loader. I’d also recommend getting rid of query_posts(). That does wonky things to the query and it is generally recommended around here to use new WP_Query.

    I’ve adjusted your batchloop.php to be a callback function instead:

    function wp_ajax_batchhandler_callback(){
    
        // Our variables  
        $posts = (isset($_GET['numPosts'])) ? $_GET['numPosts'] : 0;  
        $page = (isset($_GET['pageNumber'])) ? $_GET['pageNumber'] : 0;  
        $category = (isset($_GET['category_name'])) ? $_GET['category_name'] : 0;  
    
        var_dump($posts);
    
        $args = array(  
            'posts_per_page' => $posts,
            'category_name'  => $category, 
            'post_status'    => 'publish',
            'orderby'        => 'date',
            'order'          => 'DESC',
            'paged'          => $page 
        );
    
        $ajax_query = new WP_query($args);
    
        // our loop  
        if ($ajax_query->have_posts()) {  
    
            while ($ajax_query->have_posts()){  
                $ajax_query->the_post();  
                get_template_part( 'thumbs', get_post_format() );  
            }  
        } 
    
        // unset($page, $posts, $category);
    
        wp_reset_postdata();
    
    }
    add_action( 'wp_ajax_nopriv_batchhandler', 'batchhandler_callback' ); //logged out users
    add_action( 'wp_ajax_batchhandler', 'batchhandler_callback' ); //logged in users
    

    Like I said, I didn’t test this but it looks like you are using:

    $page = (isset($_GET['pageNumber'])) ? $_GET['pageNumber'] : 0; 
    

    To get the page number that you are using in the query. However, you aren’t sending the pageNumber in the .ajax function so I doubt you’ll get proper pagination. However, you should now be hooked up with the appropriate way to make ajax calls in WordPress, and I think pagination can be fixed by passing the pageNumber variable.