Custom Post Loop as a Gutenberg Block
Joseph Farruggio
Posted on December 19, 2018
This post was featured in Matt Mullenweg's SOTW presentation at WCUS 2018. How cool is that?
This post was originally published on my blog.
First, let's take a quick look at what we'll be building together. The image below shows the output on the front end of my customizable CPT block. In this tutorial, I'm using basic markup to output a simple and subtly styled list of testimonials, but you feel free to style it up any way you'd like.
So, in effort to spend more time and familiarize myself with Gutenberg, I wanted to convert my static front page into a Gutenberg page. One of the elements that would be handy as a block was my testimonials custom post type loop.
It turns out it was pretty easy to do. There were also some controls that I added into the block editor for a small level of configuration.
In my previous post I covered how to create a custom Gutenberg block with Advanced Custom Field’s acf_register_block().
At the time of this tutorial, Gutenberg has not yet been added into core, so we’ll need the Gutenberg plugin. We’ll also need the beta version of ACF Pro, which is currently 5.8.0 Beta. To quickly prototype my testimonial template, I'm using Tailwind.css. You'll notice the use of utility classes in my markup.
- Advanced Custom Fields – 5.8.0 Beta
- Gutenberg plugin or update to WordPress 5.0+
- Tailwind.css
Setting up the CPT
I use the free CPT UI plugin for quickly setting up custom post types.
For this CPT, I want to mainly use custom fields. So that means no classic editor or Gutenberg. In order to disable Gutenberg on CPT you need to set the “Show in REST API” to false. Set it to true if you do want to use the Gutenberg editor.
Creating the Custom Fields
Within Advanced Custom Fields I created just two fields for the testimonial; the author’s title and the quote. I’ll use the post title for the author’s name and the feature image for the author’s profile image.
Register the Testimonial Block
Within our functions.php file we’ll register our testimonial block.
functions.php
// Register Custom Blocks
add_action('acf/init', 'my_acf_init');
function my_acf_init() {
// check function exists
if( function_exists('acf_register_block') ) {
// register a testimonials block
acf_register_block(array(
'name' => 'testimonials',
'title' => __( 'Testimonials', 'wprig' ),
'description' => __( 'A custom testimonial block.', 'wprig' ),
'render_callback' => 'my_acf_block_render_callback',
'category' => 'formatting',
'icon' => 'admin-comments',
'keywords' => array( 'testimonial' ),
));
// register other blocks
acf_register_block(array(
...
));
}
}
Create the Testimonial Block Fields
I want some level of configuration over my testimonial block. Depending on where I use it, I’ll want to either loop testimonials with a ‘posts_per_page’ to set a limit or I’ll want to hand select which testimonials to display.
Back in Advanced Custom Fields we’ll create three fields to create this functionality.
In this field group I’ve created a button group to allow the user to select between limiting the post loop with a number or selecting from a list of published testimonials.
Both the ‘Testimonial Count’ and ‘Select Testimonials’ fields have a conditional argument to only be displayed based on the selection of the ‘Loop Argument Type’.
The Select Testimonials Post Object field should be set to return just the post ID.
Building the Testimonial Template
Within template-parts/blocks/content-testimonials.php I’ll create my template and add some Php to dynamically set the argument type in the loop.
template-parts/blocks/content-testimonials.php
<?php
/**
* Block Name: Testimonials
*
* This is the template that displays the testimonials loop block.
*/
$argType = get_field( 'loop_argument_type' );
if( $argType == "count" ) :
$args = array(
'orderby' => 'title',
'post_type' => 'testimonials',
'posts_per_page' => get_field( 'testimonial_count' )
);
else:
$testimonials = get_field( 'select_testimonials' );
$args = array(
'orderby' => 'title',
'post_type' => 'testimonials',
'post__in' => $testimonials
);
endif;
$the_query = new WP_Query( $args );
Next, I’ll start the loop and populate our testimonial fields in the template.
template-parts/blocks/content-testimonials.php
<?php
// Continued code
if ( $the_query->have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<div class="rounded border-b border-solid border-grey-lighter px-6 py-4 mb-2 max-w-md">
<div class="flex items-center">
<img src="<?php echo get_the_post_thumbnail_url(); ?>" class="h-12 w-12 rounded-full" />
<div class="flex flex-col ml-4">
<b class="font-bold text-black"><?php the_title(); ?></b>
<span class="text-grey"><?php echo get_field( 'authors_title', get_the_ID() ); ?></span>
</div>
</div>
<p class=" mt-3 mb-1 leading-normal text-base">
<?php echo get_field( 'quote', get_the_ID() ); ?>
</p>
</div>
<?php endwhile; ?>
<?php else: __( 'Sorry, there are no testimonials to display', 'wprig' ); endif; ?>
There’s one thing that I need to point out here to save you from some frustration. When looping through posts in a Gutenberg block, you must add the post ID as the second parameter when using ‘get_field()’.
Setting the Post ID as a second parameter
<?php echo get_field( 'quote', get_the_ID() ); ?>
Using the Testimonial Block
I want to add testimonials to my home page, so within the editor I added a testimonial block. I set the Loop Argument Type to Count and then set the Testimonial Count to 3.
If I wanted to hand pick which testimonials I wanted to display, I could set the Loop Argument Type to Select Posts:
This is a multi-select field, so I could add as many as I'd like.
And there we have it! Our custom post type is looped and applied to a custom template which is configurable and reusable as a block throughout any post or page.
--
Selfish Sales Plug Alert
Want to hire me to build you a custom Gutenberg block for your Gutenberg enabled theme?
Interested in finding out if your WordPress theme is ready and compatible with Gutenberg?
Say hello to me at joey@joeyfarruggio.com
Posted on December 19, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.