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 include both Desktop and Mobile versions for images within an ACF Repeater Field / Image Field

Today, we will show you how you can have different versions for images for your ACF Fields within WordPress. This will work for images, ACF Repeaters and so on…

Recently, we built a website and we used the ACF Repeater field to create the contents for a Carousel using Bootstrap. For this particular job, we needed to use different images for the desktop and mobile version.

So first things first, create a field for ‘Desktop Hero Image’ and a separate field for ‘Mobile Hero Image’.

For our particular example, we ended up with an ACF Repeater as below:

For the full code for a Bootstrap 4 Carousel in WordPress, see the code at the end of this post.

Now, we’ll show you what we did to have a desktop and mobile version for the hero image. If you’ve already created this, you might have a field like this:


    <span class="hero-slider" style="background-image: url(<?php the_sub_field('desktop_hero_image'); ?>);"</span>

What we need to do is amend this and create a data attribute for both the desktop and mobile version, as per the below example:


    <span class="hero-slider" style="background-image: url(<?php the_sub_field('desktop_hero_image'); ?>);" data-small-src="<?php echo get_sub_field('mobile_hero_image'); ?>"  data-lrg-src="<?php the_sub_field('desktop_hero_image'); ?>"></span>

Next, we need to add some jQuery code to change the hero image based on the browser width. In our example, we wanted to change the hero image if the window width is equal to or less than 575px. To do this, we added the below jQuery code:

<code class="language-JS">
    // Desktop/Mobile Hero Images

    var windowWidth = $(window).width();

    if (windowWidth <= 575) {
      $('[data-small-src]').each(function() {
        var small_src = $(this).data('small-src');
        $(this).css({'background-image':'url('+small_src+')'});
      });
    } else {
      $('[data-lrg-src]').each(function() {
        var lrg_src = $(this).data('lrg-src');
        $(this).css({'background-image':'url('+lrg_src+')'});
      });            
    } 

One thing to note is that the above code will only work on page load. So if you are resizing the browser, the above code will not change the image. We can, however, fix this by using the resize function. To do this, simply add the below code:

<code class="language-JS">
    // Desktop/Mobile Hero Images + Resize Function

    $(window).bind('resize',function(){

        var windowWidth = $(window).width();

        if (windowWidth <= 575) {
          $('[data-small-src]').each(function() {
            var small_src = $(this).data('small-src');
            $(this).css({'background-image':'url('+small_src+')'});
          });
        } else {
          $('[data-lrg-src]').each(function() {
            var lrg_src = $(this).data('lrg-src');
            $(this).css({'background-image':'url('+lrg_src+')'});
          });            
        }

    });

    var windowWidth = $(window).width();

    if (windowWidth <= 575) {
      $('[data-small-src]').each(function() {
        var small_src = $(this).data('small-src');
        $(this).css({'background-image':'url('+small_src+')'});
      });
    } else {
      $('[data-lrg-src]').each(function() {
        var lrg_src = $(this).data('lrg-src');
        $(this).css({'background-image':'url('+lrg_src+')'});
      });            
    } 

Well, we hope this has helped you.

If you are wanting to know how to create a basic carousel using Bootstrap 4 with an ACF Repeater, please refer to the below code:


	<!-- Home Carousel -->
	<div id="homepage-carousel" class="carousel slide carousel-fade" data-ride="carousel" data-touch="true" data-interval="6000">
		<ul class="carousel-indicators">
			<?php 
				$count = 0;
				while( have_rows('hero_carousel') ): the_row();
					if ($count == 0) {
						echo '<li data-target="#homepage-carousel" data-slide-to="0" class="active"></li>';
					} else {
						echo '<li data-target="#homepage-carousel" data-slide-to="'.$count.'"></li>';
					}
				$count++; endwhile;
			?>				
		</ul>
		<div class="carousel-inner" role="listbox">
			<?php
				if( have_rows('hero_carousel') ): $counter = 1; ?>

				    <?php while ( have_rows('hero_carousel') ) : the_row(); ?>

						<div class="carousel-item <?php echo ($counter==1)?'active':''; ?>">
							<div class="container">
						      <div class="title-container">
						            <div class="headline animated fadeInLeft">
						            	<div class="row">
						            		<div class="col-md-8">
								                <h1><?php the_sub_field('title'); ?></h1>
								                <p class="txt-headline"><?php the_sub_field('text'); ?></p>
								                <?php if(get_sub_field('button_text')) { ?>
								                	<a href="<?php the_sub_field('button_url'); ?>" class="btn"><?php the_sub_field('button_text'); ?></a>
								                <?php } ?>
								            </div>
						            	</div>
						            </div>
						       </div>
						    </div>
						    <div class="homepage-overlay">   					
					        	<span class="hero-slider" style="background-image: url(<?php the_sub_field('image'); ?>);" data-small-src="<?php echo get_sub_field('mobile_image'); ?>"  data-lrg-src="<?php the_sub_field('image'); ?>"></span>
					        </div>
						</div>

				    <?php $counter++; endwhile;
				else : endif; 
			?>
		</div>				
	</div><!-- #Home Carousel -->

As always, we hope you enjoyed this tutorial... If this has helped you, leave a comment below! Happy Coding! O_o

 

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