Blockstudio
BlocksComponents

InnerBlocks

Inner blocks allow you to insert additional blocks to your blocks. Under the hood, Blockstudio is using the InnerBlocks component. Please note that it is only possible to use one InnerBlocks component per block, this is a WordPress limitation.

Basic Usage

To use InnerBlocks, add the <InnerBlocks /> component to your block template:

index.php
<InnerBlocks />

The composition is up to you. You can nest the InnerBlocks component as deep as you want or just use it by itself.

Properties

allowedBlocks

The allowedBlocks prop allows you to define which blocks can be inserted into the InnerBlocks component.

index.php
<InnerBlocks allowedBlocks="<?php echo esc_attr(wp_json_encode(['core/heading', 'core/paragraph'])); ?>" />
index.twig
<InnerBlocks allowedBlocks="{{ ['core/heading', 'core/paragraph']|json_encode|escape('html_attr') }}" />

tag

By default, the InnerBlocks component is rendered as a div element. You can change this by using the tag prop.

index.php
<InnerBlocks tag="section" />

template

The template prop allows you to define a template for the InnerBlocks component.

index.php
<InnerBlocks template="<?php echo esc_attr(wp_json_encode([
  ['core/heading', ['placeholder' => 'Book Title']],
  ['core/paragraph', ['placeholder' => 'Summary']]
])); ?>" />
index.twig
<InnerBlocks template="{{ [
  ['core/heading', { placeholder: 'Book Title' }],
  ['core/paragraph', { placeholder: 'Summary' }]
]|json_encode|escape('html_attr') }}" />

templateLock

The templateLock prop allows you to define if the template can be modified or not.

ValueDescription
contentOnlyPrevents all operations. Block types without content are hidden from the list view. Not overrideable by children.
allPrevents all operations. Cannot insert, move, or delete blocks.
insertPrevents inserting or removing blocks, but allows moving existing ones.
falsePrevents locking from being applied even if a parent block contains locking.

renderAppender

The renderAppender prop allows you to define the block appender type.

ValueDescription
defaultDisplay the default block appender (paragraph style appender when paragraph block is allowed)
buttonDisplay a + icon button as the appender

useBlockProps

useBlockProps will remove the outer wrapper of the InnerBlocks component inside the editor. See useBlockProps for more information.

Context

Registering

Blockstudio supports context for the InnerBlocks component. This allows you to pass data from the parent block to the child blocks. While it uses the WordPress core context mechanism under the hood, Blockstudio provides a more convenient API.

Instead of having to define all attributes that should be passed in the context separately, you can simply subscribe to all attributes of a parent block.

Let's say you have a container block setup like so:

container/block.json
{
  "$schema": "https://blockstudio.dev/schema/block",
  "name": "blockstudio/container",
  "title": "Container",
  "category": "design",
  "icon": "star-filled",
  "description": "Container block.",
  "blockstudio": {
    "attributes": [
      {
        "id": "full-width",
        "type": "toggle",
        "label": "Makes section full width"
      }
    ]
  }
}

Inside your child block, simply use the usesContext property with the parent block name to gain access to all parent attributes in your block template.

element/block.json
{
  "$schema": "https://blockstudio.dev/schema/block",
  "name": "blockstudio/element",
  "title": "Element",
  "category": "design",
  "icon": "star-filled",
  "description": "Element block.",
  "usesContext": ["blockstudio/container"],
  "parent": ["blockstudio/container"],
  "blockstudio": true
}

Templates

The $context and $c variables are available inside your block templates to access all parent attributes. Child blocks will automatically reload in the editor if parent data changes.

index.php
<?php $container = $context['blockstudio/container']; ?>

<h1>
  <?php echo $container['full-width']
      ? 'is full width'
      : 'no full width'; ?>
</h1>
index.twig
{% set container = context['blockstudio/container'] %}

<h1>
  {{ container['full-width']
      ? 'is full width'
      : 'no full width' }}
</h1>

Frontend Wrapper

InnerBlocks has to render a wrapper element around its children inside the editor, however, it can be removed from the frontend by using the blockstudio/blocks/components/inner_blocks/frontend/wrap filter.

functions.php
add_filter('blockstudio/blocks/components/inner_blocks/frontend/wrap', function($wrap, $block) {
  return false; // Remove wrapper
}, 10, 2);

Return Early

If you want to return early from the render method of your block, you can check if the $innerBlocks variable is empty. This comes in handy if you don't want to render anything if there are no inner blocks.

index.php
<?php if (strip_tags($innerBlocks) === '') {
  return;
} ?>
<InnerBlocks tag="section" />

Since <InnerBlocks/> will always render an empty paragraph tag, you can use the strip_tags function to check if the content is empty.

Dynamic Templates

The Select and Radio field types support dynamically generating the InnerBlocks template depending on the field value. This is useful if you want to allow the user to select a different template for the InnerBlocks component.

To do so, simply add an innerBlocks key to the options array with the template:

block.json
{
  "$schema": "https://blockstudio.dev/schema/block",
  "name": "blockstudio/dynamic-layout",
  "title": "Dynamic Layout",
  "blockstudio": {
    "attributes": [
      {
        "id": "layout",
        "type": "select",
        "label": "Layout",
        "options": [
          {
            "value": "1",
            "label": "Two Columns",
            "innerBlocks": [
              {
                "name": "core/columns",
                "innerBlocks": [
                  {
                    "name": "core/column",
                    "innerBlocks": [
                      {
                        "name": "core/heading",
                        "attributes": {
                          "content": "Left Heading",
                          "level": 1
                        }
                      }
                    ]
                  },
                  {
                    "name": "core/column",
                    "innerBlocks": [
                      {
                        "name": "core/heading",
                        "attributes": {
                          "content": "Right Heading",
                          "level": 1
                        }
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "value": "2",
            "label": "Single Column",
            "innerBlocks": [
              {
                "name": "core/heading",
                "attributes": {
                  "content": "Main Heading",
                  "level": 1
                }
              },
              {
                "name": "core/paragraph",
                "attributes": {
                  "content": "Main content goes here."
                }
              }
            ]
          }
        ],
        "allowNull": "Select a layout"
      }
    ]
  }
}
Guide: Block Context and CommunicationLearn how parent and child blocks share data using context.

On this page