Thanks for your reply @hozefasmile
I’ve already had a look at inner blocks and they’re not quite what I’m trying to achieve. Inner blocks could definitely compose multiple “dumb” blocks together, but I’m trying to build complex blocks that don’t leave as many decisions to the user.
So I might have:
– a “dumb” icon block that knows of all possible icons (e.g. mail, phone, map or pin options) and is only in charge of rendering the icon
– a “dumb” box block that knows of all possible styling options for a box (e.g. red, green or yellow border) and is only in charge of rendering the box
– a “smart” layout block that wants to compose box and icon blocks together in a particular reusable and consistent way. The user would use this block rather than compose their own.
For example, I may need a “list of contact details in a box”.
In the output of this block, I could call a box block with a green border. No choice for the user here, the “green” attribute would be passed to the box block to render.
Within the box, I could place a repeater field which would have an icon field and a “contact detail” text field. The icon field would offer a sub-selection of what the icon block offers (“mail” or “phone” because “map” and “pin” would make no sense in this context). In the output, the selected attribute ($attributes[‘icon’]) would be passed to the icon block to do the rendering.
I’ve looked at making use of the reusable block WP functionality to “pre-compose” some blocks together but it’s not as nice as just inputting the necessary information into one block. It also doesn’t “filter/abstract” some options from the user (they can still access the icon block and select whatever icon they want).
—
I’ve actually had some luck achieving what I’m after. Hopefully, that inspires someone to improve upon my solution and share it with me and others ??
I had a look at the revision of an article using one of my icon blocks and at its simplest it looks like this:
<!-- wp:lazyblock/icon { "icon":"%selectedIconValue%", "blockId":"%generaredId%", "blockUniqueClass":"lazyblock-icon-%generaredId%"} /-->';
If your block has a bunch of other attributes, they will be listed in there too with their value. There are a bunch of reserved attributes names passed in by WordPress that might be listed there too, such as “className”, “anchor” (which are hidden in the “Advanced” accordion in the WP block editor), “align” and some that look to be lazyblock specific: “lazyblock”.
I’ve looked around for how WP then renders that string into HTML and found out about do_blocks($content) which basically parses the whole article and then iterates over each block (the above one included) to render them.
So I’ve made use of what I learned to render other blocks from within the output of my “smart” block.
It basically looks like this:
<?php
// Prepare icons for later
$iconTemplate = '
<!-- wp:lazyblock/icon
{
"icon":"%s"
}
/-->';
// first icon
$icon1Value = "value-of-icon-to-render";
$icon1 = do_blocks( sprintf( $iconTemplate, $icon1Value ) );
// second icon
$icon2Value = "value-of-other-icon-to-render";
$icon2 = do_blocks( sprintf( $iconTemplate, $icon2Value ) );
// Later on, display the icons wherever necessary in your template
echo $icon1;
echo $icon2;
?>
“icon” is one of the attributes on the icon block.
You can map more key-value pairs against your attributes by editing the json object accordingly (adding %s as a placeholder for the dynamic value and adapting the dynamic value as an extra parameter to the sprintf() function).
I haven’t tried passing data to repeater fields yet, but I’m assuming it would be something like "attribute": [{"inner1": "value1","%s": "%s"}, {"inner1": "%s","inner2": "%s"}}]
I haven’t figured out how I could render an icon block within a box block yet though. The box block should not have an icon attribute to pass data to as it shouldn’t concern itself with its content (it would need to know of all possible blocks otherwise).
I haven’t looked at using inner blocks for that yet.
It’s worth noting that, while this currently works for me, there might be an entirely different and way better approach than mine.
If there is, I would love to hear it ??