When you see a list of results, there’s usually some form of pagination going on. It’s not always feasible to load everything at once, so results are broken up into sections. This could be 10 or 20 results for something, like posts on a blog site or products on an e-commerce site.

Nowadays more sites use more dynamic options to load more results, options that don’t require a user navigating to another page of results, but instead simply loading more results and appending them to the page. This can be done with a button click, or with some kind of user interaction like scrolling to a certain point on the page. The scrolling type of interaction is useful in certain situations, like if you’re scrolling on Facebook or Twitter, but on most sites, an automatic load can be detrimental to the user experience. On a normal website, you could have other content below such as a footer with links to other pages, and when more results keep loading, it stops the user from accessing those. The best solution in cases like this is to use a load more button, that when clicked loads more results. That tends to be the most user-friendly option to load more results.

As part of a recent build for Atlantic Culturescape, I needed to build some layouts with the feature of a load more. (Thanks, Dean). To be honest, this is very simple in WordPress. With a little bit of jQuery and PHP, you can set up the ability to load more results with the click of a button. Because this site uses this feature in many places, I also wanted to build it in a way that would be easily repeatable, instead of duplicating a bunch of code.

Ajax Code for generating the extra results

To load more results, we have to use the wp_ajax_{$action} and wp_ajax_nopriv_{$action} hooks. These call the load_more_posts() function where ever more results are needed. The post type can vary so the same function can be used but it can differ in which card layout is returned.

add_action('wp_ajax_load_more', 'load_more_posts');
add_action('wp_ajax_nopriv_load_more', 'load_more_posts');

function load_more_posts() {

    if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'load_more_nonce')) {
        exit;
    }

    $args = json_decode( stripslashes( $_POST['query'] ), true );
    $args['paged'] = $_POST['page'] + 1;
    $args['post_status'] = 'publish';
    $post_type = $args['post_type'];

    query_posts( $args );

    if (have_posts()):

        while (have_posts()) : the_post();

            if($post_type === 'galley') {
                single_gallery_card();
            }
            elseif($post_type === 'experiences'){
                single_experience_card();
            }

            //... etc etc
      
            else {
                //do nothing
            }

        endwhile;

    endif;

    die;
}

Conditional Load More Button

For the load more button, this is wrapped in a conditional to see if there is multiple pages or not, as the button isn’t needed if there’s only one page of results.

<?php global $wp_query;
if (  $wp_query->max_num_pages > 1 ) : ?>

   <button id="load-more" class="btn">Load More</button>

<?php endif;

JavaScript for fetching and appending the posts

There needs to be some JavaScript, or jQuery in this case, to fetch the extra results. It takes into account the current page query as well as the current page of results that’s been loaded. When fetching, the button text is updated to “Loading…”, but other actions could be used here depending on what kind of affect you want.

$('#load-more').click(function(){

        var button = $(this),
            data = {
                'action': 'load_more',
                'query': load_more.posts,
                'page' : load_more.current_page,
                'nonce': load_more.nonce
            };

        $.ajax({
            url : load_more.ajaxurl,
            data : data,
            type : 'POST',
            beforeSend : function ( xhr ) {
                button.text('Loading...');
            },
            success : function( data ){
                if( data ) {

                    //reset button text
                    button.text( 'Load More' );

                    //append new data
                    $('.load-more-target').append(data);

                    load_more.current_page++;
                    if ( load_more.current_page == load_more.max_page )
                        button.remove();

                } else {
                    button.remove();
                }
            }
        });
    });

Global js variables

The wp_localize_script() function can be used to pass data to the JS script above. This is how the post data is passed back to the wp_ajax function.

global $wp_query;
wp_enqueue_script('load-more', get_template_directory_uri() . 'path-to-load-more.js', array(), '1.0.0', true);

wp_localize_script( 'load-more', 'load_more', array(
    'ajaxurl' => site_url() . '/wp-admin/admin-ajax.php',
    'posts' => json_encode( $wp_query->query_vars ),
    'current_page' => get_query_var( 'paged' ) ? get_query_var('paged') : 1,
    'max_page' => $wp_query->max_num_pages,
    'nonce' => wp_create_nonce('load_more_nonce')
) );

archive.php

Finally, there’s a couple things needed where you’re displaying the results. In this case, it’s in archive.php in the theme. I’ve used a class here on the containing <div> to target where to add the results.

<div class="row load-more-target">

    <?php if (have_posts()): 
        while (have_posts()): the_post();
            
            card_for_this_post_type();
            
        endwhile; 
    endif; ?>
    
</div>

<?php load_more_button(); ?>

The standard posts per page is 10, so you would need at least 11 for the “Load More” button to display and for it to pull in the eleventh result. You could easily change this in Settings > Reading to say, 5 results per page, and then each click of the load more button will add 5 more results instead of 10.

Viola! The Load more button in action.

If you want to implement something similar into your own WordPress website contact Wibble and we will be happy to help.