Inner Blocks are Gutenberg Blocks that allow inserting additional blocks within your own block. To understand it even better, imagine a shortcode that wraps the content. This content can then be shown or hidden. You can achieve that inside Gutenberg with Inner Blocks.

Article Changelog:

2020-03-26 – Added new InnerBlocks properties (templateInsertUpdatesSelection, renderAppender, and __experimentalCaptureToolbars), Added CoBlocks Accordion Example.

Gutenberg Inner Blocks

If you’re interested in reading the code behind Inner Blocks, you can check their folder on Github. They are basically a wrapper that allows putting other blocks inside.

How do you use them? First, you need to import them in the file where you’re going to use them.

import { InnerBlocks } from ' @wordpress/editor ' ; // or wp.editor

Then you need to insert this block inside your edit function (this example uses JSX):

edit ( { className } ) { return ( < div className = { className } > < InnerBlocks /> </ div > ); },

To show the contents (other blocks) inside of the InnerBlocks component, you need to call <InnerBlocks.Content/> :

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

Properties

This block (component) also accepts several properties so that you can customize the UX of your block.

allowedBlocks

This property can be a string or an array containing names of registered blocks. As the property name suggests, this can be used to allow certain blocks only inside of your Inner Blocks component.

In this example, I am allowing only the image block (and all the child blocks).

<InnerBlocks allowedBlocks={ 'core/image' } />

In this example, I am allowing the image block and the paragraph block (and all the child blocks).

Child Blocks?

So, what are these child blocks? These blocks will always be allowed inside of Inner Blocks. You can register child blocks by providing a parent property. For example:

So, if you specifically set a few blocks that are allowed in the Inner Block component, the child blocks will also be available.

template

The template property is something like a starter content for your Inner Block component. When you add your block, the inner block component will be already filled with the specified blocks.

An interesting and useful thing is that you can also set the attributes within such blocks.

Here is an example of an Inner Block component with 2 paragraphs which have different placeholders.

templateInsertUpdatesSelection

This property will let the block be updated with all the blocks when a new one is added. If set to false , it will not update the selection of all the blocks.

Default is true .

In many cases, you probably won’t need to change this, but if you are wondering when you would, here are some of the components/blocks in Gutenberg that set this to false .

Media Text block – https://github.com/WordPress/gutenberg/blob/master/packages/block-library/src/media-text/edit.js

Media Text Native block – https://github.com/WordPress/gutenberg/blob/master/packages/block-library/src/media-text/edit.native.js

Navigation Block – https://github.com/WordPress/gutenberg/blob/master/packages/block-library/src/navigation/edit.js

templateLock

This property can decide if you can add, remove and move the blocks inside the Inner Block component. Possible options are:

all – nothing is allowed

– nothing is allowed insert – you can’t remove or add new blocks, but you can move the existing ones,

– you can’t remove or add new blocks, but you can move the existing ones, false – everything is allowed, even if the parent block is locked.

If nothing is set, it will use the locking value of the parent block.

renderAppender

This can be a function or false . Default is undefined (no function defined).

If nothing is defined (not false or function), the component DefaultBlockAppender will be used. The default block will be usually the paragraph block if not configured otherwise in wp.blocks.setDefaultBlockName .

There are also two appenders set under the InnerBlocks component:

InnerBlocks.ButtonBlockAppender -> add a “+” button that when clicked will show the block picker menu,

-> add a “+” button that when clicked will show the block picker menu, InnerBlocks.DefaultBlockAppender -> same as the above DefaultBlockAppender.

You can also pass a different custom function to show an appender:

// Fully custom <InnerBlocks renderAppender={ () => ( <button className="bespoke-appender" type="button">Some Special Appender</button> ) } />

For example, the Group block has this to show an appender or not:

<Block.div className={ className }> <div className="wp-block-group__inner-container"> <InnerBlocks renderAppender={ hasInnerBlocks ? undefined : () => <InnerBlocks.ButtonBlockAppender /> } /> </div> </Block.div>

They have a check hasInnerBlocks and if that’s true , then it won’t show the ButtonBlockAppender .

__experimentalCaptureToolbars

This is false by default. If set to true , when we are editing a block inside of the InnerBlocks, the toolbar of that block will show on the InnerBlocks container (at the top).

How CoBlocks are using InnerBlocks

We will now check the CoBlocks Accordion block to see how they utilize the InnerBlocks for creating accordion items.

First, they only allow their own coblocks/accordion-item block.

Here is how they call this component:

<InnerBlocks template={ getCount( count ) } allowedBlocks={ ALLOWED_BLOCKS } />

The getCount() function does not actually returns the count of blocks, but for every block (accordion item) they have, they create an accordion item block. The default count is set to 1, so the template will always show 1 accordion item.

Accordion Item block

Let’s now see how the Accordion Item works. This block is set to be allowed only as a child block for their Accordion block:

Each Accordion Item is using InnerBlocks as well and here they also use the parameter templateInsertUpdatesSelection . So, when a new block is added to this item, the focus won’t trigger so that the parent block might get focused and the focus will be left as it was before.

<InnerBlocks template={ TEMPLATE } templateInsertUpdatesSelection={ false } />

The template of this item will use the paragraph block when we add an accordion item.

Creating a Premium Content Block

This will be a block that will have the Inner Block component that will be used for adding the premium content. We can also decide if these content will be available for users with unpaid or paid membership.

That way, you could have a content that is displayed to the members and another “teaser” content to the visitors.

In a previous tutorial, I have written an article on Integrating Gutenberg Blocks in Existing WordPress Plugins where you can see how to create a Webpack configuration for your blocks.

For this tutorial, I am going to use the Create-Guten-Block tool. If you have the latest npm , then position yourself inside of the plugins folder and run:

npx create-guten-block inner-blocks cd inner-blocks npm start

You can also open the folder inner-blocks in your editor and change the plugin information. After that, activate your new plugin.

Registering the Block

Open now inner-blocks/src/block/block.js and edit the information to match this:

We have changed the slug of it and added a new attribute paid . This will hold the value true or false and it will indicate if this content is for members or visitors.

The Edit Function

The edit function is the one that will be called to render the Block inside of the Gutenberg editor. In this function we will call the Inner Block component.

We are using the InspectorControls to render the setting in the block settings. With the SelectControl component, we are rendering the options. With onChange attribute we are setting the attribute paid when we select a different value.

The Save Function

This function is used for the content that is saved inside of the post content. Since we will also register our block with PHP, the save function will be used only for rendering the content that we will hide or show.

Dynamic Block Content

To have a dynamic block content, we need to register the block inside of PHP. Open src/init.php and add this:

We also need to define the function that will now process the block content. This can be also an existing shortcode function if you have one.

The Code

With this file, you’ll get the complete plugin in the development mode. You would need to run npm build to build the JavaScript for production. Also, inside of this code, you’ll see a child block example and also the usage of template and allowedBlocks properties.

This part is available only to the members. If you want to become a member and support my work go to this link and subscribe: Become a Member

Conclusion

With the usage of inner blocks component, we can replace all the available shortcodes that are wrapping the content.