it says "no preview available" and no description is added, even though I've defined both in the code
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.
You can see on the right hand side, that the paragraph block has an image and description alongside it.
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 using registerBlockType()
:
registerBlockType( 'my-blocks/foo-bar', {
title: 'My Foo Bar block',
category: 'formatting',
description: 'Sample description.',
// Just define this property and there'll be a preview.
example: {},
// And the preview is the one coming from this callback.
edit: () => <p>just testing the block previews :)</p>,
save: () => null,
} );
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 the example
arg:
example
(Array) (Optional) An array of structured data used to construct a preview shown within the block-inserter. All values
entered into the ‘data’ attribute array will become available within
the block render template/callback via $block['data']
or
get_field()
.
So in your case, you would add that arg to your $hero
array:
$hero = array(
'name' => 'hero',
'title' => __( 'Hero' ),
'description' => __( 'Hero section' ),
'render_callback' => 'block_render',
'category' => 'formatting',
'icon' => 'admin-comments',
'keywords' => array( 'hero' ),
// Just add this and you'll get the block preview:
'example' => array(
'attributes' => array(
'mode' => 'preview',
),
),
);
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:
function block_render( $block, $content = '', $is_preview = false ) {
// back-end preview
if ( $is_preview ) {
echo 'A Hero block using ACF — In preview mode.';
return;
}
// front-end output
echo 'A Hero block using ACF.';
}
And if you want a different preview in the inserter UI and the editor, then set the data
arg in the example
arg, and in the render callback, just check if the data
is not empty:
/* In $hero, add example.attributes.data:
$hero = array(
'name' => 'hero',
...
'example' => array(
'attributes' => array(
'mode' => 'preview',
'data' => array(
'my_field' => 'Sample value',
),
),
),
);
*/
function block_render( $block, $content = '', $is_preview = false ) {
// back-end previews
if ( $is_preview && ! empty( $block['data'] ) ) {
echo 'A Hero block using ACF — In preview mode — In the block inserter UI.';
return;
} elseif ( $is_preview ) {
echo 'A Hero block using ACF — In preview mode — In the editor.';
return;
}
// front-end output
echo 'A Hero block using ACF.';
}
And actually, you could show an actual image via those if
:
if ( $is_preview && ! empty( $block['data'] ) ) {
echo '<img src="https://example.com/path/to/image-file-name.png">';
return;
}
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.