I've created a batch of custom ACF gutenberg
blocks and now trying to assign a preview image.
Issue: Getting the preview image to show
The below image here shows a paragraph
component which is a default block.
You can see on the right hand side, that the paragraph block has an image and description alongside it. Below is how my component is currently appearing (full code will be at the end)
As you can see, it says "no preview available" and no description is added, even though I've defined both in the code.
Approach:
acf-blocks/blocks.php
<?php
$img_root = "../../src/components";
$hero = array(
'name' => 'hero',
'title' => __('Hero') ,
'description' => __('Hero section') ,
'render_callback' => 'block_render',
'category' => 'formatting',
'icon' => 'admin-comments',
'image' => $img_root . '/hero/hero.png',
'mode' => 'edit',
'keywords' => array(
'hero'
) ,
);
$blocks = [$hero];
return $blocks;
?>
acf-blocks/functions.php
<?php
function block_acf_init(){
$path = get_template_directory().'/inc/acf-blocks/blocks.php';
$blocks = require($path);
foreach($blocks as $block) {
acf_register_block_type($block);
}
}
if( function_exists('acf_register_block_type') ) {
add_action('acf/init', 'block_acf_init');
}
?>
My folder structure is as follows:
theme
inc
acf-blocks
blocks.php
functions.php
src
components
hero
hero.js
hero.scss
hero.png
Unsure why my preview image doesn't show?
Edit:
I've added the block_render
function but still no success. Here is my current functions.php
file:
<?php
$component_path = "../../src/components" . strtolower($block['title']) . strtolower($block['title']).".js";
function block_render( $block, $content = '', $is_preview = false ) {
$context = get_context();
$context['block'] = $block; // store block values
$context['fields'] = get_fields(); // store field values
$context['is_preview'] = $is_preview;
render($component_path, $context ); // render the block
}
function block_acf_init(){
$path = get_template_directory().'/inc/acf-blocks/blocks.php';
$blocks = require($path);
foreach($blocks as $block) {
acf_register_block_type($block);
}
}
if( function_exists('acf_register_block_type') ) {
add_action('acf/init', 'block_acf_init');
}
?>
Edit 2:
<?php
$hero = array(
'name' => 'hero',
'title' => __('Hero'),
'description' => __('Add hero section'),
'render_callback' => 'block_render',
'category' => 'formatting',
'icon' => 'admin-comments',
'mode' => 'edit',
'category' => 'custom',
'post_types' => array(
'page'
),
'keywords' => array(
'hero'
),
'example' => array(
'mode' => 'preview',
'data' => array(
'field' => 'value' // sample data
)
)
);
function block_render($block, $content = '', $is_preview = false)
{
if ($is_preview && !empty($block['data'])) {
echo '<img src="https://i.picsum.photos/id/1021/536/354.jpg?hmac=XeUbyCXoxX2IrSELemo2mRl4zVXzhjFyxtj3GTVZ8xo">';
return;
} elseif ($is_preview) {
echo 'A Hero block using ACF';
return;
}
echo 'A Hero block using ACF.';
}
?>
Have even tried:
<?php
function block_render( $block, $content = '', $is_preview = false ) {
if($is_preview):
echo '<img src="https://i.picsum.photos/id/1021/536/354.jpg?hmac=XeUbyCXoxX2IrSELemo2mRl4zVXzhjFyxtj3GTVZ8xo">';
else:
echo '<img src="https://i.picsum.photos/id/1021/536/354.jpg?hmac=XeUbyCXoxX2IrSELemo2mRl4zVXzhjFyxtj3GTVZ8xo">';
endif;
}
?>
In both cases, when trying to show the image (not the block preview), I see the ACF fields for the block, not the dummy image defined:
It says "no preview available" because it's indeed so, and what you defined is not something that ACF or even WordPress supports, i.e. the
image
arg ('image' => $img_root . '/hero/hero.png'
) will do nothing out-of-the-box.No, that is not an image.
It is instead a preview of the block output as returned by the block's render callback (which is the
block_render()
function in your case) or template in the case of an ACF block type.And that (core) Paragraph block, it actually defines the
example
property which then enables the block preview even if the property is empty (i.e. no attributes defined). Working example usingregisterBlockType()
:And with that, you'd get this preview:
But I provided that example just to let you know how would you add a preview to a non-dynamic block.
So how to add the block preview via ACF
Simple, and as shown in the other answer as well as the
acf_register_block_type()
documentation, use theexample
arg:So in your case, you would add that arg to your
$hero
array:And basically, whatever the render callback/template outputs, would be what you see in the preview when adding the block via the block inserter UI.
But if you want a different output when on preview mode — both when inserting the block via the UI and after the block is added into the editor, then you can make use of the
$is_preview
parameter passed to the render callback:And if you want a different preview in the inserter UI and the editor, then set the
data
arg in theexample
arg, and in the render callback, just check if thedata
is not empty:And actually, you could show an actual image via those
if
:which then gives you a preview that looks like:
So I hope that helps? :)
And note that the examples have been tried & tested working with ACF Pro 5.9.4 and WordPress 5.6, which both are the latest releases as of writing.