Raquel M Smith

How to Create Nested Blocks for Gutenberg

The power of Gutenberg lies in its blocks. Everything is a block. 

But the coolest thing I’ve seen that you can accomplish with said blocks is nested blocks

Nested blocks are blocks within blocks. You can have a single level of nesting, or you can even allow multiple levels of nesting – blocks within blocks within blocks.

With nested blocks, you can even set a template, so that when the block is added to the page, all the inner blocks are already there. Further, if you don’t want the blocks inside the main block (the parent) to ever change, you can lock the block. Pretty nifty!

Here’s an example – this is a single block that’s added with a single click of a button:

A nested block in the Gutenberg editor

As with most Gutenberg documentation, it can be difficult to find information on how to use these things. Let’s take a look.

Create a block

First things first, get your block basics all set up. I’m not going to go into details here, but I recommend watching Zac Gordon’s Gutenberg Development course. You can use his example plugin as a start and go from there, or you can copy the requisite files and bits of code into your existing plugin. 

Another good place to start might be create-guten-block, but again, that’s a topic we’ll cover at another time.

If you’re not super familiar with Javascript development, it’s probably a good idea to brush up on your modern JS skills. I recommend Wes Bos’s free ES6 for Everyone and React for Beginners courses. Those will get you comfortable with whatever is going on here. you can certainly start with just Zac’s course linked above, but I always think it’s a good idea to have some general background knowledge to really ground what you’ll be learning with Gutenberg development.

Register InnerBlocks

InnerBlocks is available from the wp.editor package. So, we want to pull this in at the top of our block file.

In the same area where you added the other block libraries, such as:

const { __ } = wp.i18n;
const { registerBlockType } = wp.blocks;

You’ll want to add the InnerBlocks library. Add the following:

const { InnerBlocks } = wp.editor;

Add InnerBlocks to the edit function

Now that InnerBlocks is available for use, we’ll want to add it to the edit function for the block. We’ll wrap it in a <div> with the block className for CSS targeting.

edit: props => {
	const { className } = props;
	return [
		<div className={className}>
			<InnerBlocks />
		</div>
	];
}

Cool! Your block officially accepts more blocks inside of it.

Save the InnerBlocks content

We want to make sure the editor is able to save the nested blocks and re-load them there when the page is next opened. So, in our save function, we save the content from the InnerBlocks:

save: props => {
	return (
		<div>
			<InnerBlocks.Content />
		</div>
	);
}

Cool! Save your code, then give it a shot. You should be able to add your block, then add other blocks inside your block. 

Set which blocks are allowed

If you want to allow only a certain subset of allowed blocks, you can set that in the <InnerBlocks> component properties.

In the edit function, add a property to InnerBlocks for allowedBlocks, and pass in an array of blocks that can be used.

edit: props => {
	const { className } = props;
	return [
		<div className={className}>
			<InnerBlocks
				allowedBlocks={['core/paragraph']}
			/>
		</div>
	];
},

The example above will allow only new paragraph blocks to be added to the main block. 

If you’re building something special, like a modifiable list of homes for sale, you can build the custom inner block, then set it as the only block allowed in the parent.

Add a nested block template

Block templates are really cool. When your main block is added to the page, it’ll automatically add all the child blocks according to the template. It allows you to set certain types of content and layout within the main parent block right from the get-go.

The block template should be added as a constant to the block file, probably right below where you add the block libraries. The template is a multidimensional array of child blocks. For example:

const TEMPLATE = [
	['my/block', {}, []],
	['my/other-block', {}, []],
]

Each block sits inside its own array and takes three values:

  1. The block namespace, in single quotes
  2. An object of block attributes that you want to set immediately
  3. An array with more nested blocks
    • This allows you to create nested block templates for blocks you don’t necessarily have code control over, like the core/columns block.

Here’s a real-life example:

const TEMPLATE = [
	['core/heading', { placeholder: 'Recipe Title' }],
	['core/columns', {},[
		['core/column', {}, [
			['core/image']
		]],
		['core/column', {},[
			['core/paragraph', { placeholder: 'Enter short recipe description...' }],
			['core/paragraph', { placeholder: 'Enter ingredients...' }],
			['core/button', { text: 'Make this Recipe' }],
			['pinchofyum/listicle-item-attribution']
			]
		]
	]
]];

In that example, the template includes a heading, then a columns block, with two columns. The first column has an image block, and the second has a couple paragraphs, a button, and an attribution section.

Now, we need to add this template to our <InnerBlocks> component. To do this, just add a template property to the component in the edit function:

<InnerBlocks template={TEMPLATE} />

Lock the template

If you want to make sure that the child blocks don’t change, you can lock the template. There are three options for this:

  1. all – Locking the template completely, so that no blocks can be added, removed or reordered
  2. insert – Locking the template partially, so blocks can be reordered, but not added or removed
  3. false – no locking; blocks can be added, removed, and reordered

Again, this is a property for the <InnerBlocks> component in the editor.

<InnerBlocks 
	template={TEMPLATE} 
	templateLock="all" 
/>

Now, my block has a template set that defines the layout, automatically adds all the necessary child blocks, and prevents the child blocks from being reordered, added, or removed.

Neato! Last thing…

Set the parent for strictly child blocks

If a block you’ve made is meant to be used only inside one type of other block, then you can set the parent for that block.

An example is the column block. The core/column block can only be added inside a core/columns block. You can’t add a column randomly to the page – it has to be inside a columns block.

To do this, you’ll set the parent on the child block. You’ll do this where you set the block title, description, category, etc. Add another block property called parent set it to an array containing the block parent name(s).

For example:

title: 'Listicle Item',
description: 'An item for the Listicle block.',
category: 'formatting',
icon: 'shield',
keywords: ['List item'],
parent: ['pinchofyum/listicle'],

Now, this block will only show up as an option when I’m adding a nested block to the parent block (pinchofyum/listicle, in this case).

Nested blocks are cool!

One reason I love the idea of nested blocks is because it allows us to reuse blocks that already exist for new applications. This prevents us from having to rewrite code that’s already been written – we’re keeping DRY here. 

Nested blocks have a ways to go with functionality – or maybe I just haven’t discovered it. Such as – how can I use the InnerBlocks.Content to write structured data to the front end? Can I get access to that content from the main block? If you know how to do this, let me know in the comments. Otherwise, I’ll be working on figuring it out over the next couple of weeks.

Now go build some nested blocks in Gutenberg!

Leave a Reply

Your email address will not be published. Required fields are marked *

20 Comments on "How to Create Nested Blocks for Gutenberg"

  1. Nikola Ivanov

    March 12, 2019

    This is the only example where everything is explained perfectly for the child / parent blocks, locking etc.. I’ve been searching whole day. Good job, and thank you! 🙂

    1. Raquel Smith

      March 16, 2019

      Glad you found it helpful, Nikola!

  2. Minna Perälä

    March 06, 2019

    Do you happen to know why block styles cause an error (when clicking styles in inspector) for a nested block and styles selection is not in the toolbar? I’ve defined block styles for nested block in the same way I define those for regular blocks.

  3. Chris

    February 28, 2019

    Awesome tutorial – thank you. Question: is it possible for a child nested block to directly access any of the data or settings from the parent block?

  4. Nora

    February 12, 2019

    This was very helpful to me. I appreciate that it starts out with the basics, but builds to something quite sophisticated. Thank you!

    1. Raquel Smith

      February 26, 2019

      Glad you found it helpful, Nora!

  5. Melanie Müller

    January 29, 2019

    Hi! I love this article and it is very helpful to me.

    But I cant import my own blocks nested. If I use core-blocks everything works fine.
    Core:
    [‘core/image’, { className: ‘card-image-top’ }],

    Myblock:
    [‘bootstrapblocks/divblock’, { className: ‘card-image-top’ }],

    any idea?

    1. Raquel Smith

      February 26, 2019

      Hey Melanie,

      Sorry for the delay here. Did you get your problem worked out? If not, I’d double-check the name of the block and make sure that’s correct, and also make sure the block parent isn’t set to something else.

      1. Raquel Smith

        March 09, 2019

        Hey Melanie,

        Did you ever get this worked out?

  6. Steve Lombardi

    January 23, 2019

    I am trying to restrict a block to a parent. I want my “pbdsblocks/textblock” block to only appear inside my “pbdsblocks/section” block.

    So I set parent: [“pbdsblocks/section”]

    But then the block does not show up for insertion anywhere; not inside a section block.

    1. Raquel Smith

      January 27, 2019

      Hm, setting the parent in the child block should allow it to show up. Without any of your actual code I’m not able to help debug much. Sorry!

  7. Steve Lombardi

    January 22, 2019

    Can you add a Classic Editor block to a template? I tried “core/classic” but that doesn’t work, not sure of the “official” name…

    1. Raquel Smith

      January 27, 2019

      Hey Steve,

      I’m not sure if you can include a classic block inside another block. My intuition is no, since the Classic block is meant as a transitional block between the Classic and Block editor, and you can’t just add a Classic block from the Block editor UI.

  8. David Carr

    January 12, 2019

    Is there a good way of preventing a block with InnerBlocks enabled from being inserted inside itself? I don’t want to restrict the blocks that can be inserted within the container block much, but I’m finding it’s way too easy to insert another copy of the container block inside the outer container block. Because I’m working with a formatting-oriented wrapper, I get some pretty funky formatting when it happens accidentally.

    I experimented with using wp.blocks.getBlockTypes() to retrieve the whole list, then filtering it down to a an allowedblocks array that omits my wrapper block, but it seems like there ought to be a better way.

    (Also: weird unexpected behavior, when I tried that, was that my block disappeared from the pick list both inside and outside the wrapper block).

    1. Raquel Smith

      January 12, 2019

      Hm, I haven’t personally run into this situation. Every custom nested block I’ve made I’ve explicitly set what can go inside the block – usually with a locked template, or with the allowedBlocks attribute. If I come across this use-case in my projects and come up with a better solution then I will let you know!

  9. Erik

    November 26, 2018

    Is it possible to make nested blocks at the dashboard? I am not savvy enoubh to do all this programming…

    1. Raquel Smith

      January 11, 2019

      Hey Erik,

      You can create a column block, then add your desired blocks to that, then save it as a template. Templates can be reused in other posts. They don’t have special styling or advanced features like the custom nested blocks I’m talking about here can have, but they are useful in their own right!

  10. Vidit Goyal

    November 24, 2018

    How to create a container block or nested block in the current version of WordPress after the InnerBlocks has been deprecated.

    1. Raquel Smith

      January 11, 2019

      Hi Vidit,

      I’m not aware that InnerBlocks has been deprecated. Do you have a link?

  11. Muhammad Zohaib

    November 12, 2018

    Very helpfull. Thanks