Using a Template with InnerBlocks in the WordPress Block Editor (Gutenberg)

·

When you create a block in the WordPress Block Editor (Gutenberg) you can create an area that allows other block types to be nested inside your block. You do this with the InnerBlocks component.

In our other guides we previously explored block patterns and block templates. This guide looks at creating a template for nested blocks.

Prerequisites

Create a Nested Block Plugin

After you have carried out the steps in the creating a Gutenberg plugin tutorial, up to (but not including) step 5, you should have the framework in place to create the nested block plugin.

Add InnerBlocks to /src/edit.js

Open up /src/edit.js in your editor and replace the import for useBlockProps with the following:

import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';

This will let us use the InnerBlocks component in our edit render method.

Then change the entire Edit function to thefollowing:

export default function Edit() {
    return (
        <div { ...useBlockProps() }>
            <InnerBlocks/>
        </div>
    );
}

This registers the InnerBlock

Output the Attributes in /src/save.js

Open up /src/save.js in your editor and replace the import for useBlockProps with the following:

import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';

This will let us use the InnerBlocks component in our save render method.

Next output the content of the Innerblocks component by replacing the save function with the following:

export default function save() {
    return (
        <div { ...useBlockProps.save() }>
            <InnerBlocks.Content />
        </div>
    );
}

This simply outputs the value of the InnerBlocks into a <div>.

Compiling the Plugin

Open the terminal, make sure you are in the root directory of your plugin and run the following command:

npm start

The script will compile. If you have any errors the terminal should make you aware of what they are.

Adding the InnerBlocks Template

To keep things simple we are going to use the exact same template we previously created for the block patterns and the block template guide.

The template is very similar to the one we defined in our block template guide, however the attributes are in an object instead of a multidimensional array.

Replace the Edit function with the following code:

export default function Edit() {
    return (
        <div { ...useBlockProps() }>
            <InnerBlocks
                template={ [
                    [ 'core/heading', { level: 2, content: 'Example Nested Block Template' } ],
                    [ 'core/paragraph', { content: 'Lorem ipsum dolor sit amet labore cras venenatis.' } ],
                    [ 'core/columns', {},
                        [
                            [ 'core/column', {}, [
                                    [ 'core/heading', { level: 3, content: 'Sub Heading 1' } ],
                                    [ 'core/paragraph', { content: 'Lorem ipsum dolor sit amet id erat aliquet diam ullamcorper tempus massa eleifend vivamus.' } ],
                                ]
                            ],
                            [ 'core/column', {}, [
                                    [ 'core/heading', { level: 3, content: 'Sub Heading 2' } ],
                                    [ 'core/paragraph', { content: 'Morbi augue cursus quam pulvinar eget volutpat suspendisse dictumst mattis id.' } ],
                                ]
                            ],
                        ]
                    ],
                ] }
                templateLock="all"
            />
        </div>
    );
}

This creates a template for the nested block. Note the use of templateLock which is set to all. This behaves the same as the template lock for the block template and has the following two options:

  • all — prevents all operations. It is not possible to insert new blocks, move existing blocks, or delete blocks.
  • insert — prevents inserting or removing blocks, but allows moving existing blocks.

You can also define which blocks are allowed within the nested blocks.

  1. Inserting and Viewing the InnerBlocks Template

You can insert the nested block the same way as any other block, by clicking the plus icon and searching for Wholesome Plugin.

Inserting the Nested Block Template

Inserting the Nested Block Template

Note that as before, the nested blocks inside the nested blocks do not have the template lock applied to them.

There are of course workarounds for this, by being creative with how you create a combination of block templates and custom nested blocks.

Viewing the Block

After a little bit of tinkering with the SCSS, our outputted block looks a little something like this:

Inserting the Nested Block Template

Inserting the Nested Block Template

Extra: Allowed Blocks for Nested Blocks

Instead of locking the template, you could instead restrict it by stating which blocks you are allowed to insert into it. Simply replace the Edit function with the following code:

export default function Edit() {
    return (
        <div { ...useBlockProps() }>
            <InnerBlocks
                template={ [
                    [ 'core/heading', { level: 2, content: 'Example Nested Block Template' } ],
                    [ 'core/paragraph', { content: 'Lorem ipsum dolor sit amet labore cras venenatis.' } ],
                    [ 'core/columns', {},
                        [
                            [ 'core/column', {}, [
                                    [ 'core/heading', { level: 3, content: 'Sub Heading 1' } ],
                                    [ 'core/paragraph', { content: 'Lorem ipsum dolor sit amet id erat aliquet diam ullamcorper tempus massa eleifend vivamus.' } ],
                                ]
                            ],
                            [ 'core/column', {}, [
                                    [ 'core/heading', { level: 3, content: 'Sub Heading 2' } ],
                                    [ 'core/paragraph', { content: 'Morbi augue cursus quam pulvinar eget volutpat suspendisse dictumst mattis id.' } ],
                                ]
                            ],
                        ]
                    ],
                ] }
                allowedBlocks={ [
                    'core/column',
                    'core/columns',
                    'core/heading',
                    'core/paragraph',
                ] }
            />
        </div>
    );
}

Here we omit the templateLock argument and instead restrict our nested block to the following blocks:

  • Column (core/column)
  • Columns (core/columns)
  • Group (core/group)
  • Heading (core/heading)
  • Paragraph (core/paragraph)

Again, this won’t work on any nested blocks within the template.

Extra: Taking it Further