Overview
ACF 6.0 introduces support for WordPress’s block.json
method of block registration, the recommended way of registering blocks since WordPress 5.8 and newer. You don’t have to upgrade your blocks, but you’ll need to do so if you want to take advantage of new WordPress functionality like attribute defaults (for things like background colors) or block assets loading for compatibility with block patterns.
It’s a relatively quick and painless process to upgrade your blocks from the acf_register_block_type
method in ACF 5 to the new block.json
format, and in this guide we’ll demonstrate how to upgrade our testimonial
block from the ACF 5 documentation to a block.json
block.
Let’s start with the old block example:
functions.php
add_action('acf/init', 'my_acf_blocks_init');
function my_acf_blocks_init() {
// Check function exists.
if( function_exists('acf_register_block_type') ) {
// Register a testimonial block.
acf_register_block_type(array(
'name' => 'testimonial',
'title' => __('Testimonial'),
'description' => __('A custom testimonial block.'),
'render_template' => 'template-parts/blocks/testimonial/testimonial.php',
'mode' => 'preview',
'category' => 'formatting',
));
}
}
template-parts/blocks/testimonial/testimonial.php
<?php
/**
* Testimonial Block Template.
*
* @param array $block The block settings and attributes.
* @param string $content The block inner HTML (empty).
* @param bool $is_preview True during AJAX preview.
* @param (int|string) $post_id The post ID this block is saved to.
*/
// Create id attribute allowing for custom "anchor" value.
$id = 'testimonial-' . $block['id'];
if( !empty($block['anchor']) ) {
$id = $block['anchor'];
}
// Create class attribute allowing for custom "className" and "align" values.
$className = 'testimonial';
if( !empty($block['className']) ) {
$className .= ' ' . $block['className'];
}
if( !empty($block['align']) ) {
$className .= ' align' . $block['align'];
}
// Load values and handle defaults.
$text = get_field('testimonial') ?: 'Your testimonial here...';
$author = get_field('author') ?: 'Author name';
$role = get_field('role') ?: 'Author role';
$image = get_field('image') ?: 295;
$background_color = get_field('background_color');
$text_color = get_field('text_color');
?>
<div id="<?php echo esc_attr( $id ); ?>" class="<?php echo esc_attr( $className ); ?>">
<blockquote class="testimonial-blockquote">
<span class="testimonial-text"><?php echo esc_html( $text ); ?></span>
<span class="testimonial-author"><?php echo esc_html( $author ); ?></span>
<span class="testimonial-role"><?php echo esc_html( $author_role ); ?></span>
</blockquote>
<div class="testimonial-image">
<?php echo wp_get_attachment_image( $image, 'full' ); ?>
</div>
<style type="text/css">
#<?php echo esc_attr( $id ); ?> {
background: <?php echo esc_attr( $background_color ); ?>;
color: <?php echo esc_attr( $text_color); ?>;
}
</style>
</div>
Upgrading Your Block
To upgrade this block, we need to turn the code into a new block.json
file, which contains a JSON object of all the settings for the block.
If you want to store blocks in your theme, you need to make sure you’re using WordPress 6.0 which introduced support for that. If you’re storing them in a plugin, you need at least WordPress 5.8.
blocks/testimonial/block.json
{
"name": "acf/testimonial",
"title": "Testimonial",
"description": "A custom testimonial block.",
"style": [ "file:./testimonial.css" ],
"category": "formatting",
"icon": "admin-comments",
"keywords": ["testimonial", "quote"],
"acf": {
"mode": "preview",
"renderTemplate": "testimonial.php"
},
"align": "full"
}
The key changes in the transition from the old method is that all ACF specific configuration now lives inside an acf
key. You can view the full options for that array in our ACF block.json
documentation.
You’ll also notice that the WordPress convention for block.json
files is that all property keys are camelCase. We’ve respected this in ACF’s configuration, and anything that used to contain underscores is now camelCased, for example render_template
is now renderTemplate
.
Asset Loading
Another major change regards asset loading. Instead of using the enqueue_script
, enqueue_style
functions, or an enqueue_assets
callback, you should use the new WordPress provided block asset functions. You’re mostly to use script
or style
which will load your assets in both the backend editor, and the frontend view too. Although there are options which will load separate assets in each view if you prefer.
For all the asset properties of your block.json
file, you can either pass an asset handle which has already been registered before you register your block as a string – or you can use the file:./filename.css
method above.
This is a custom format called a WPDefinedAsset. You can also add a filename.asset.php
which provides some metadata for your asset, such as dependencies and versions. This is useful to ensure your block also has things like jQuery available. See the WPDefinedAsset documentation for full details of this.
Most of these options also support arrays of multiple files, but be aware of the version of WordPress that introduced support for multiple assets for the type of asset loading you’re using.
If you opt to use wp_register_style()
or wp_register_script()
style handles, we recommend you register them on the line before you load the block to ensure it’s available.
Loading the New block.json Block
Registering the block is as simple as using the WordPress native function register_block_type
, for which you pass a path to the folder containing the block.json
file. If you prefer, you can instead pass the full path to the block.json
, but it is important to note your block must be called block.json
to load. No other file names are allowed as of WordPress 6.0.
We also recommend registering the block earlier than acf/init
, so we use the WordPress default of init
. You may also find if you want to use script or style handles you should pass a priority earlier than the default of 10. In our example below we use 5.
functions.php
add_action( 'init', 'register_acf_blocks', 5 );
function register_acf_blocks() {
register_block_type( __DIR__ . '/blocks/testimonial' );
}
This should be all you need to do to upgrade your ACF 5 block to an ACF 6 block! Your existing templating will still work and shouldn’t need any changes, although we’ve got a few notes on that below.
Templating
Our previous ACF 5 documentation for blocks showed the following method of applying styles specific to a block, using the $block['id']
:
<style type="text/css">
#<?php echo esc_attr( $id ); ?> {
background: <?php echo esc_attr( $background_color ); ?>;
color: <?php echo esc_attr( $text_color ); ?>;
}
</style>
Various new WordPress features since 5.8, such as the Query Loop block and Block Patterns, mean using either of those features would result in $id
duplication.
In ACF 6.0, we’ve changed block IDs to overcome this, and while we still generate one for your template, if you have two copies of the exact same block on a page, their IDs will still be the same. For this reason, you should not rely on the $block['id']
being unique, and not use it to target CSS classes.
Instead, we’ve updated our testimonial template file to build a style
property which is added to the DOM element instead:
block/testimonial/testimonial.php
<?php
/**
* Testimonial Block Template.
*
* @param array $block The block settings and attributes.
* @param string $content The block inner HTML (empty).
* @param bool $is_preview True during backend preview render.
* @param int $post_id The post ID the block is rendering content against.
* This is either the post ID currently being displayed inside a query loop,
* or the post ID of the post hosting this block.
* @param array $context The context provided to the block by the post or its parent block.
*/
// Support custom "anchor" values.
$anchor = '';
if ( ! empty( $block['anchor'] ) ) {
$anchor = 'id="' . esc_attr( $block['anchor'] ) . '" ';
}
// Create class attribute allowing for custom "className" and "align" values.
$class_name = 'testimonial-block';
if ( ! empty( $block['className'] ) ) {
$class_name .= ' ' . $block['className'];
}
if ( ! empty( $block['align'] ) ) {
$class_name .= ' align' . $block['align'];
}
// Load values and assign defaults.
$text = get_field( 'testimonial' ) ?: 'Your testimonial here...';
$author = get_field( 'author' ) ?: 'Author name';
$author_role = get_field( 'role' ) ?: 'Author role';
$image = get_field( 'image' ) ?: 295;
$background_color = get_field( 'background_color' );
$text_color = get_field( 'text_color' );
// Build a valid style attribute for background and text colors.
$styles = array( 'background-color: ' . $background_color, 'color: ' . $text_color );
$style = implode( '; ', $styles );
?>
<div <?php echo $anchor; ?>class="<?php echo esc_attr( $class_name ); ?>" style="<?php echo esc_attr( $style ); ?>">
<blockquote class="testimonial-blockquote">
<span class="testimonial-text"><?php echo esc_html( $text ); ?></span>
<span class="testimonial-author"><?php echo esc_html( $author ); ?></span>
<span class="testimonial-role"><?php echo esc_html( $author_role ); ?></span>
</blockquote>
<div class="testimonial-image">
<?php echo wp_get_attachment_image( $image, 'full' ); ?>
</div>
</div>