Too Long ; Didn't Read

How do I get pagination to work when I'm creating my query with ajax?

I'm working on creating a functional search page that allows the user to filter how many posts per page. I don't quite understand how to create it so pagination functions correctly and was hoping somebody could explain it to me. I understand that by creating a new query in my PHP ajax action I thus create new paging and do not alter the normal WP_Query, so I would need to make my pagination function with ajax but i'm not sure how I would connect it to a certain ajax custom query.

function implement_ajax() {

    $ppp = 10;
        $ppp = $_GET['ppp'];

    $search = $_GET['s'];           // Acquired and sent via ajax
    $paged = 1;
        $paged = $_GET['paged'];

    $temp = new WP_Query(array('s' => $search, 'posts_per_page' => $ppp));

    $numPosts = $temp->post_count;
    $foundPosts = $temp->found_posts;
    $lastPage = $temp->max_num_pages;

    if($temp->have_posts()) :
        $i = 0; 
        <?php if($temp->max_num_pages > 1) : ?>
            <div class="pagination">
                    $big = 999999999;
                    echo paginate_links(array('base' => '/', 'format' => '?paged=%#%', 'current' => max( 1, get_query_var('paged') ), 'total' => $temp->max_num_pages)); 
                <div class="clear"></div>
            </div> <!-- class="pagination" -->
        <?php endif; ?>

        <div id="postContainer">
            <?php while($temp->have_posts()) : 

                <div class="custom-post<?php echo ($i%2 == 0) ? ' even' : ''; echo ($i == $numPosts) ? ' last' : ''; echo ($i == 1) ? ' first' : ''; ?>">
                    <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
                    <?php the_excerpt(); ?>
                </div> <!-- class="custom-post" -->

            <?php endwhile; ?>
        </div> <!-- id="postContainer" -->

    <?php else : ?>
        <div id="postContainer">
            <div id="content">
                <p>No articles found.</p>
                <p><a href="<?php echo home_url(); ?>">Return Home</a></p>  
            </div> <!-- id="content" -->
        </div> <!-- id="postContainer" -->
    <?php endif;

    $htmlContent = ob_get_clean();
    echo $htmlContent;
add_action('wp_ajax_nopriv_implement_ajax', 'implement_ajax');
add_action('wp_ajax_implement_ajax', 'implement_ajax');

The above returns the correct query - but pagination is broken since I'm not sure how to set the base parameter. I've tried ('/?s='.$search.'?paged='.$paged) and / and a few other ones that have gotten me nowhere. If I use the 'Basic Example' in The Codex: str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ) paginate_links return:


which does return the correct posts, minus the header, footer, and styles.

I tried to duplicate what G.M did in this question with localize script but couldn't get past $args = (array) filter_var(INPUT_POST, 'query'); since parameter 2 was expecting an integer. I tried to just convert my $_POST['query'] to an array but wasn't able to do so.

Relevant File Pastebins:

  1. Search Page
  2. Relevant Functions
  3. Ajax Jquery

Warning - there may be some relics in there, I've been commentings things in and out to try and get this to work.

  • What is the actual base of your search page, meaning the literal path: http://domain.com/your/search/page/%_%?
    – Milo
    Mar 31, 2014 at 20:00
  • www.mydomain.com/?s=web - but if there's paging it goes into www.mydomain.com/page/2/?s=web - most my results though (via ajax) are putting paging into the query var (?paged=2) instead of rewriting it.
    – Howdy_McGee
    Mar 31, 2014 at 20:03
  • you get that format because that's what you set the format to in your paginate_links args
    – Milo
    Mar 31, 2014 at 20:12

1 Answer 1


I think this is what you want. base is set via home_url(), format is page/%#%/, search query arg is added via add_args if it exists:

$args = array(
    'base' => home_url( '/%_%' ),
    'format' => 'page/%#%/',
    'current' => max( 1, get_query_var('paged') ),
    'total' => $temp->max_num_pages,

if( isset($_GET['s']) ){
    $args['add_args'] = array(
        's' => $_GET['s'] // your search query passed via your ajax function

echo paginate_links( $args );
  • I think one of the main problems is that I'm generating paginate links from my ajax call - which when I try to locate page 2 it doesn't know how / where to find it. Like I can't even use get_query_var in my ajax php function call.
    – Howdy_McGee
    Mar 31, 2014 at 20:19
  • it knows where to find it in this example because you set it to an absolute value via home_url(). you're right about get_query_var and the search value, my bad, you have to pass that via javascript.
    – Milo
    Mar 31, 2014 at 20:22
  • the thing to remember about paginate_links is that it's not a typical template tag that operates from global vars and whatnot- it's a general purpose pagination function designed to generate links for any type of pagination, and as such it relies completely on you explicitly setting every aspect of what you want as output.
    – Milo
    Mar 31, 2014 at 20:25
  • Ok, so I was able to pull the page via Jquery - now though whenever I click to go to the second page, it brings up the 2nd page of the original WP_Query. So if I click my selectbox 5 posts per page - it runs my ajax, shows 5 posts and the correct pagination, then when I go to page 2 the pagination reverts and it goes back to the original WP_Query of 10 ppp. Thanks for your help btw! - I think I need to connect my paginate_links with my new WP_Query or modify the main WP_Query via ajax (which seems impossible without a full page reload).
    – Howdy_McGee
    Mar 31, 2014 at 20:43
  • 1
    you don't maintain state from one page to the next. when you click a pagination link you run the normal query using the default posts per page. you need to figure out some way to pass what the new posts per page value is in those pagination links and use that value on the next page reload.
    – Milo
    Mar 31, 2014 at 23:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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