How to Load More Posts using Ajax with a Button or on Scroll in WordPress

Updated: 22/01/2021 – Further clarification has been added on the setup of this script.

In today’s post, we will show you how to create a load more button to show additional posts or custom post types using AJAX.

The benefit of this is that it will improve the page-load of the particular page as it will only be displaying a certain amount of posts before having to load any more of the content (especially when you are loading images).

So let’s get started…

So the first thing that you should have is a list of posts to display on the frontend as follows:-


    <div id="ajax-posts" class="row">
        <?php
            $postsPerPage = 3;
            $args = array(
                    'post_type' => 'post',
                    'posts_per_page' => $postsPerPage,
            );

            $loop = new WP_Query($args);

            while ($loop->have_posts()) : $loop->the_post();
        ?>

         <div class="small-12 large-4 columns">
                <h1><?php the_title(); ?></h1>
                <p><?php the_content(); ?></p>
         </div>

         <?php
                endwhile;
        wp_reset_postdata();
         ?>
    </div>
    <div id="more_posts">Load More</div>

Then you want to add the following code in your functions.php file where you register the scripts:


	wp_localize_script( 'core-js', 'ajax_posts', array(
	    'ajaxurl' => admin_url( 'admin-ajax.php' ),
	    'noposts' => __('No older posts found', 'twentyfifteen'),
	));	

NOTE: You will need to replace code-js with the file you are going to be adding the JS code later in this tutorial.

We added it to a file called core.js, and the reason we added code-js is that we enqueued the script as follows:


	wp_register_script( 'core-js', get_template_directory_uri() . '/assets/js/core.js');
	wp_enqueue_script( 'core-js' );

Right after the existing wp_localize_script. This will load WordPress own admin-ajax.php so that we can use it when we call it in our ajax call.

At the end of the functions.php file, you need to add the function that will load your posts:-


function more_post_ajax(){

    $ppp = (isset($_POST["ppp"])) ? $_POST["ppp"] : 3;
    $page = (isset($_POST['pageNumber'])) ? $_POST['pageNumber'] : 0;

    header("Content-Type: text/html");

    $args = array(
        'suppress_filters' => true,
        'post_type' => 'post',
        'posts_per_page' => $ppp,
        'paged'    => $page,
    );

    $loop = new WP_Query($args);

    $out = '';

    if ($loop -> have_posts()) :  while ($loop -> have_posts()) : $loop -> the_post();
        $out .= '<div class="small-12 large-4 columns">
                <h1>'.get_the_title().'</h1>
                <p>'.get_the_content().'</p>
         </div>';

    endwhile;
    endif;
    wp_reset_postdata();
    die($out);
}

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

The final part is the ajax itself. In functions.js or your main JavaScript/jQuery file, you need to input inside the $(document).ready(); environment the following code:-


var ppp = 3; // Post per page
var pageNumber = 1;


function load_posts(){
    pageNumber++;
    var str = '&pageNumber=' + pageNumber + '&ppp=' + ppp + '&action=more_post_ajax';
    $.ajax({
        type: "POST",
        dataType: "html",
        url: ajax_posts.ajaxurl,
        data: str,
        success: function(data){
            var $data = $(data);
            if($data.length){
                $("#ajax-posts").append($data);
                $("#more_posts").attr("disabled",false);
            } else{
                $("#more_posts").attr("disabled",true);
            }
        },
        error : function(jqXHR, textStatus, errorThrown) {
            $loader.html(jqXHR + " :: " + textStatus + " :: " + errorThrown);
        }

    });
    return false;
}

$("#more_posts").on("click",function(){ // When btn is pressed.
    $("#more_posts").attr("disabled",true); // Disable the button, temp.
    load_posts();
    $(this).insertAfter('#ajax-posts'); // Move the 'Load More' button to the end of the the newly added posts.
});

With the above code, you should now have a load more button at the bottom of your posts, and once you click this it will display further posts. This can also be used with CTP (custom post type).

How to add Infinite Load, instead of Click

You can also load the rest of the posts automatically on scroll instead of having to click on a button. This can be achieved by making it invisible by setting the visibility to hidden.

The following code will run the load_posts() function when you’re 100px from the bottom of the page. So instead of the click function we added we would use:


$(window).on('scroll', function(){
    if($('body').scrollTop()+$(window).height() > $('footer').offset().top){
        if(!($loader.hasClass('post_loading_loader') || $loader.hasClass('post_no_more_posts'))){
                load_posts();
        }
    }
});

Do note that there is a drawback to this. With this method, you could never scroll the value of $(document).height() - 100 or $('footer').offset().top, If that should happen, just increase the number where the scroll goes to.

You can easily check it by putting console.log in your code and see in the inspector what they throw out like so:


$(window).on('scroll', function () {
    console.log($(window).scrollTop() + $(window).height());
    console.log($(document).height() - 100);
    if ($(window).scrollTop() + $(window).height()  >= $(document).height() - 100) {
        load_posts();        
    }
});

Adjust the settings accordingly and you will get this working to your desire in no time!

If you need any help with this, feel free to get in touch in the comment below. If you need help with this, just drop me a message and I’ll be more than happy to help you!

 


Sponsor

If you have come this far and you’re a fan of Football, check out our sponsor below; The FPL Way

They will help you become the king of your FPL mini-leagues!


Fantasy Premier League – Gain the FPL advantage you deserve

 

Nathan da Silva - Profile

Posted by: Nathan da Silva

Nathan is the Founder of Silva Web Designs. He is passionate about web development, website design and basically anything digital related. His main expertise is with WordPress, Magento, Shopify as well as many other frameworks. Whether you need responsive design, SEO, speed optimisation or anything else in the world of digital then get in touch. If you would like to work with Nathan, simply drop him an email at [email protected]

It’s good to share

ACF Repeater Load More using AJAX

Have you ever wanted to show a limited amount of items when using an ACF repeater? Maybe you are using this to display images and to save on load time you only want to show a selective amount instead of loading them all. At the end of the day, having to load fewer images is going to speed up your site right?

In this example, we will show you the basics of adding load more functionality for an ACF repeater field. We are going to display a repeater called gallery and load only 9 items if there are more than 9 items we will display a ‘Load more’ button to programmatically load the rest.

So first of all our markup will look as follows:-


<div id="photo-gallery">
	<div class="row">
		<?php
		if( have_rows('media') ): 
			$total = count(get_field('media'));
			$count = 0;
			$number = 8;					
			while ( have_rows('media') ) : the_row(); ?>						
					<div class="col-md-4 col-sm-6">
						<a class="mag-pop" data-img="<?php the_sub_field('image'); ?>" href="<?php the_sub_field('image'); ?>"><img class="img-gallery" alt="BeWILDerwood Gallery" src="<?php the_sub_field('image'); ?>" /></a>
					</div>
				<?php
				if ($count == $number) {
					// we've shown the number, break out of loop
					break;
				} ?>					
			<?php $count++; endwhile;
		else : endif;
		?>
	</div>
	<a id="gallery-load-more" href="javascript: my_repeater_show_more();" <?php if ($total < $count) { ?> style="display: none;"<?php } ?>><h2 id="title-bg"><span>Load more</span></h2></a>
</div>

As you can see, $number defined the number of repeater items we want to initially display. We use the break; clause to prevent further images from loading.

Now moving on to the JavaScript:-


<script type="text/javascript">
	var my_repeater_field_post_id = <?php echo $post->ID; ?>;
	var my_repeater_field_offset = <?php echo $number + 1; ?>;
	var my_repeater_field_nonce = '<?php echo wp_create_nonce('my_repeater_field_nonce'); ?>';
	var my_repeater_ajax_url = '<?php echo admin_url('admin-ajax.php'); ?>';
	var my_repeater_more = true;
	
	function my_repeater_show_more() {
		
		// make ajax request
		jQuery.post(
			my_repeater_ajax_url, {
				// this is the AJAX action we set up in PHP
				'action': 'my_repeater_show_more',
				'post_id': my_repeater_field_post_id,
				'offset': my_repeater_field_offset,
				'nonce': my_repeater_field_nonce
			},
			function (json) {
				// add content to container
				// this ID must match the containter 
				// you want to append content to
				jQuery('#photo-gallery .row').append(json['content']);
				// update offset
				my_repeater_field_offset = json['offset'];
				// see if there is more, if not then hide the more link
				if (!json['more']) {
					// this ID must match the id of the show more link
					jQuery('#gallery-load-more').css('display', 'none');
				}
			},
			'json'
		);
	}
	
</script>

We’ve added comments within the code so you can see what is happening through the process. Now we need to add the code to the functions.php file to load the additional items.


/**
 * ACF Load More Repeater
*/

// add action for logged in users
add_action('wp_ajax_my_repeater_show_more', 'my_repeater_show_more');
// add action for non logged in users
add_action('wp_ajax_nopriv_my_repeater_show_more', 'my_repeater_show_more');

function my_repeater_show_more() {
	// validate the nonce
	if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'my_repeater_field_nonce')) {
		exit;
	}
	// make sure we have the other values
	if (!isset($_POST['post_id']) || !isset($_POST['offset'])) {
		return;
	}
	$show = 9; // how many more to show
	$start = $_POST['offset'];
	$end = $start+$show;
	$post_id = $_POST['post_id'];
	// use an object buffer to capture the html output
	// alternately you could create a varaible like $html
	// and add the content to this string, but I find
	// object buffers make the code easier to work with
	ob_start();
	if (have_rows('media', $post_id)) {
		$total = count(get_field('media', $post_id));
		$count = 0;
		while (have_rows('media', $post_id)) {
			the_row();
			if ($count < $start) {
				// we have not gotten to where
				// we need to start showing
				// increment count and continue
				$count++;
				continue;
			}
			?>
			<div class="col-md-4 col-sm-6">
				<a class="mag-pop" data-img="<?php the_sub_field('image'); ?>" href="<?php the_sub_field('image'); ?>"><img class="img-gallery" alt="BeWILDerwood Gallery" src="<?php the_sub_field('image'); ?>" /></a>
			</div>
			<?php 
			$count++;
			if ($count == $end) {
				// we have shown the number, break out of loop
				break;
			}
		} // end while have rows
	} // end if have rows
	$content = ob_get_clean();
	// check to see if we have shown the last item
	$more = false;
	if ($total > $count) {
		$more = true;
	}
	// output our 3 values as a json encoded array
	echo json_encode(array('content' => $content, 'more' => $more, 'offset' => $end));
	exit;
} // end function my_repeater_show_more

As you can see above, we are going to load an additional 9 images (or repeater values) on click of the load more button. Once all loaded items have appeared, we are hiding the load more button so that is no longer visible.

And that’s pretty much it! If this has helped you, feel free to drop a comment. If you need any help with this, feel free to get in touch and we’ll be happy to assist you! 🙂

 

Nathan da Silva - Profile

Posted by: Nathan da Silva

Nathan is the Founder of Silva Web Designs. He is passionate about web development, website design and basically anything digital related. His main expertise is with WordPress, Magento, Shopify as well as many other frameworks. Whether you need responsive design, SEO, speed optimisation or anything else in the world of digital then get in touch. If you would like to work with Nathan, simply drop him an email at [email protected]

It’s good to share

How to Skip the Cart Page and Go Straight to the Checkout Page in WooCommerce

Some people may find the process of ordering a product (especially if it’s a simple product) too long of a process. You can provide a better user experience for this by skipping the cart page and going straight to the checkout process. We recently developed a site where the purpose was to book online courses, in this situation, most often, users would just buy a single course at a time. That being said, this is why we decided to simplify the process and allow users to book courses a lot quicker.

The first thing you will need to do is navigate to WooCommerce -> Settings -> Products.

You will want to uncheck the following options:

  • Redirect to the basket page after successful addition
  • Enable AJAX add to basket buttons on archives

Once you have done this, simply add the following code to your functions.php file:


/**
 *	Bypass WooCommerce Cart
 */

add_filter('woocommerce_add_to_cart_redirect', 'silva_add_to_cart_redirect');
function silva_add_to_cart_redirect() {
	global $woocommerce;
	$checkout_url = wc_get_checkout_url();
	return $checkout_url;
}

And as simple as that, now when you click a product to add to basket, it will now redirect directly to the checkout page.

Taking it one step further, what we can also do is change the label of the ‘Add to Cart’ button.

How to Change the ‘Add to Cart’ label

Now that we have removed the cart from the checkout process, it now makes sense to change the label in the WooCommerce product. In our example, we are going to replace this with ‘Buy Now’. To achieve this, WooCommerce has a filter which again, we can add to the functions.php file as shown below:


/**
 *	Add New Pay Button Text
 */

add_filter( 'woocommerce_product_single_add_to_cart_text', 'silva_cart_button_text' ); 
 
function silva_cart_button_text() {
 return __( 'Buy Now', 'woocommerce' );
}

What this filter is doing is applying the text changes to the single product page. It could be that you have the product on another post type, for this; there is a second filter you can also use

The above filter applies the text to the single product page, however, you may have the product on another post type, there is a 2nd filter you can also use; woocommerce_product_add_to_cart_text as shown below:


/**
 *	Add New Pay Button Text
 */

add_filter( 'woocommerce_product_single_add_to_cart_text', 'silva_cart_button_text' ); 
add_filter( 'woocommerce_product_add_to_cart_text', 'silva_cart_button_text' ); 
 
function silva_cart_button_text() {
 return __( 'Buy Now', 'woocommerce' );
}

With all the above completed, we now have fewer steps to the key part of your e-commerce website; allowing your customers to purchase products quicker by simplifying the process!

Well, we hope you enjoyed this article, if you need help in any way, feel free to contact us or drop a comment below and we’d love to help you.

 

Nathan da Silva - Profile

Posted by: Nathan da Silva

Nathan is the Founder of Silva Web Designs. He is passionate about web development, website design and basically anything digital related. His main expertise is with WordPress, Magento, Shopify as well as many other frameworks. Whether you need responsive design, SEO, speed optimisation or anything else in the world of digital then get in touch. If you would like to work with Nathan, simply drop him an email at [email protected]

It’s good to share

jQuery – Submitting a form with AJAX

To submit a form with AJAX (without reloading the page), you can use the ajaxForm/ajaxSubmit functions from Ajax Form Plugin or the jQuery serialize function.

AjaxForm:


$("#theForm").ajaxForm({url: 'server.php', type: 'post'})

or alternatively:-


$("#theForm").ajaxSubmit({url: 'server.php', type: 'post'})

ajaxForm will send when the submit button is pressed. ajaxSubmit sends immediately.

Serialize Method:


$.get('server.php?' + $('#theForm').serialize())

$.post('server.php', $('#theForm').serialize())

You can read the AJAX serialization documentation is here.

 

Nathan da Silva - Profile

Posted by: Nathan da Silva

Nathan is the Founder of Silva Web Designs. He is passionate about web development, website design and basically anything digital related. His main expertise is with WordPress, Magento, Shopify as well as many other frameworks. Whether you need responsive design, SEO, speed optimisation or anything else in the world of digital then get in touch. If you would like to work with Nathan, simply drop him an email at [email protected]

It’s good to share