Currently InnerBlocks
can only be rendered once into any block.
I can see there's been a lot of discussion around nested blocks so I'm sure there's a valid reason for this limitation but would be great to be able to be able to render multiple per block. The specific use case I'm thinking about is for a tabbed/accordion block with multiple content panes. Within each content pane you may want to have images or embeds etc.
This would be addressed in part by the inline blocks being discussed #2043 but allowing multiple InnerBlocks
would provide more flexibility.
@t-wright An alternative solution to the accordion block having multiple <InnerBlocks/>
would be to have an accordion block with a single <InnerBlocks/>
which only allows an accordion item block, which would have its own <InnerBlocks/>
that allows any block to be inserted into it. One neat bonus of having each accordion item being a separate block is that you get the drag-and-drop reordering of blocks for free, plus the ability to have different styles for each accordion item.
There is one caveat, though, and it is that the UI might be a bit tricky for something like a tabbed block. An accordion block would be easy to implement with the standard block UI, but a tabbed block sounds like something that may require special coding.
So in the case of a tabbed container block, perhaps there is a need for the ability to have multiple <InnerBlocks/>
after all. This also raises the question of how/if the block nesting UI should adapt for things that do not list vertically.
Actually, now that I think about it, the tabbed block could probably be handled by having the block look different depending on whether or not it is selected. If unselected, the block would look pretty much like it does on the front-end, but when selected, each tab would appear as a block, all stacked vertically (like in any other container block). That is of course not the most ideal situation as it makes the block look different while it is being edited, but it does show that it is technically possible to have such a block in Gutenberg already.
Thanks for giving this one some thought @SuperGeniusZeb. That's an approach I hadn't thought of and I think it makes sense. And getting re-ordering for free is a massive benefit too! I'll have a crack and see how I go. Ultimately I think the API and UI could be a more intuitive if multiple <InnerBlocks />
were permitted but I think the approach you've suggested will work for my current requirements. Thanks again.
Multiple inner blocks have complexities that don't seem worth the effort, and in general it either hints at a block that should be broken down into multiple simpler blocks, or with block attributes (not children). Let us know how the above suggestion work for you and we could revisit.
I am late on this topic but like to share one use case where multiple <InnerBlocks />
might be useful. I am building a block where front end renders two columns and it is not fixed what would go in each column. If multiple <InnerBlocks />
is supported with a sort of unique key
and <InnerBlocks.Content />
can be rendered using the key
it would be easier to build such blocks. But right now there is no option to create it. Native colummn
block has this support but in this particular scenario that cannot be used since the columns need to have separate classes. How would one accomplish this?
@emfluenceindia the way I've approached a similar problem is to create my own parent and child blocks. The parent block renders an <InnerBlocks />
components which accepts the child block as a nested block.
The child block has an <InnerBlocks />
which you could wrap in a div. You could set the class on the div directly or in my case, I pass a value to a customClasses
attribute on my child block to set the class dynamically. Check the docs for more on this - https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-templates/
<InnerBlocks
allowedBlocks={ [ 'cgb/column' ] }
template={[
[ 'cgb/column', {
customClasses: 'is-active',
} ],
]}
/>
I know probably there's some complexity to implement it, I think it can use the concept of named slots like all major javascript frameworks have.
Sometimes is a pain in the neck to split in unnecessary blocks just to have this behavior...
What would it take to get this issue opened back up? It seems like the dual answers of "it's too difficult for us to pull off" and "block developers can figure out workarounds with a combination of our template system and creating additional-sub blocks that serve no other purpose" are, at least on some level, a bit at odds with each-other. The use cases for multiple Inner Block sections are virtually endless.
It's worth noting that some experimental enhancements to the InnerBlocks API have been made in #24232, allowing the children blocks to each be wrapped with a given set of markup, for example:
<InnerBlocks
__experimentalItemCallback={ ( item ) => (
<>
<section>{ item }</section>
<p>You can do cool/weird stuff like this now.</p>
</>
) }
/>
This is great for list-style blocks that want to wrap each child in a <li>
(or any other element or elements), or for adding markup before and after each child.
With these new API additions in mind, does anyone still think multiple InnerBlocks
areas are necessary? It's worth noting that conceptually, the InnerBlocks
area represents the children of a block. DOM nodes only have one set of children, and right now, blocks can only have one set of children.
Allowing blocks to have multiple InnerBlocks
areas would be... weird. It would make the logic in Select/Navigation mode a lot more convoluted, it would require rewrites to the List View tool, and it would drastically alter how block children are treated throughout the code. When you go to insert a block inside one of the areas, the inserter can no longer check the block's "allowed children" list, because there could now potentially be a different one for each InnerBlocks
area. The InnerBlocks
= "the block children" metaphor would suddenly break, and a lot of simple code would have to become noticeably more complex... and for what benefit?
Ultimately, what's wrong with using sub-blocks with their own InnerBlocks
areas? It encapsulates logic and automatically solves the aforementioned Select mode and List View problems automatically. If there's any problem to solve here, it would be making it easier to traverse up and down the block hierarchy. (I'm actually working on this in #23800, though I've run into a bit of a roadblock.)
If you have multiple content areas in a block, then conceptually, each of those areas are already a sort of "block" of content. So why not just actually use blocks for them? From a code quality perspective, that seems a lot better to me. Each sub-block would already have access to the usual APIs for allowed-children, templates, variations, and so on, because it's just a normal block. If you try to go the multiple InnerBlocks
route, you end up having to reimplement all of that.
So basically, I don't think using sub-blocks is a workaround; rather, I view it as the most logical solution when you're dealing with multiple sets of children. I think having multiple InnerBlocks
would be the actual hacky workaround. It forces you to complicate both conceptual design and almost every block-related API... all so you can accomplish the same thing you could already accomplish. You end up gaining so little at the cost of so much.
Agreed with @ZebulanStanphill. Multiple inner block areas add unnecessary complexity to the block API, grammar, and parsing logic and provide very little value over the existing setup. As mentioned before, intermediary blocks that are hidden from inserters can be used to handle more complex cases (like core's own _Columns_ block) while preserving parsing unambiguity, which is an important architecture consideration for long term stability and performance. I also haven't seen concrete case articulated so far where multiple block areas would actually result in a better implementation compared to using the currently recommended mechanism. Perhaps we need more examples in the documentation that target the perceived need for multiple inner blocks?
Just a simple question. How is this current accomplished with the multiple column layout block within WordPress? Just the fact that this exists seems to make me think there is a way to do it.
"intermediary blocks that are hidden from inserters"
If this isn't "unnecessary complexity for the block API and grammar" then I don't know what is. It should be plainly obvious that nothing about that is intuitive vs nested blocks from that sentence alone, and you can't complain about a feature making the api too hard to understand when the absence of the feature also creates a whole other layer of implementation complexity for your end-users.
Imagine something simple as this example...
{
edit: () => {
return (
<section>
<aside>
<InnerBlocks name="sidebar"/>
</aside>
<div className="content">
<InnerBlocks />
</div>
</section>
);
},
save: () => {
return (
<section>
<aside>
<InnerBlocks.Content name="sidebar"/>
</aside>
<div className="content">
<InnerBlocks.Content />
</div>
</section>
);
},
}
For now I'm solving with a Block Template. Which is fine, it works. I had to override some of the standard styles, and I suppress the add-new column option with CSS. I applied a grid style to .wp-block-columns
, which designates positioning for each column (> .wp-block-column:nth-of-type(1)
). Works fine if the user adds extra columns, but not sure what I'm going to do if the user removes columns.
Lucky for me, this isn't a pubic endeavor, so I can simply ask them not to do that.
const BLOCKS_TEMPLATE = [
['core/columns', {}, [
['core/column', {}, [
['core/image'],
]],
['core/column', {}, [
['core/paragraph', { placeholder: 'Enter side content...' }],
]],
]]
];
Most helpful comment
What would it take to get this issue opened back up? It seems like the dual answers of "it's too difficult for us to pull off" and "block developers can figure out workarounds with a combination of our template system and creating additional-sub blocks that serve no other purpose" are, at least on some level, a bit at odds with each-other. The use cases for multiple Inner Block sections are virtually endless.