Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nested block / inner block to tutorial #17559

Merged
merged 6 commits into from Jan 2, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,164 @@
# Nested Blocks: Using InnerBlocks

You can create a single block that nests other blocks using the [InnerBlocks](/packages/block-editor/src/components/inner-blocks) component. This is used in the Columns block, Social Links block, or any block you want to contain other blocks.

Note: A single block can only contain one `InnerBlock` component.

Here is the basic InnerBlocks usage.

{% codetabs %}
{% ES5 %}
```js
( function( blocks, element, blockEditor ) {
var el = element.createElement;
var InnerBlocks = blockEditor.InnerBlocks;

blocks.registerBlockType( 'gutenberg-examples/example-06', {
title: 'Example: Inner Blocks',
category: 'layout',

edit: function( props ) {
return el(
'div',
{ className: props.className },
InnerBlocks
mkaz marked this conversation as resolved.
Show resolved Hide resolved
);
},

save: function( props ) {
return el(
'div',
{ className: props.className },
InnerBlocks.Content
mkaz marked this conversation as resolved.
Show resolved Hide resolved
);
},
} );
} (
oandregal marked this conversation as resolved.
Show resolved Hide resolved
window.wp.blocks,
window.wp.element,
window.wp.blockEditor,
) );
oandregal marked this conversation as resolved.
Show resolved Hide resolved
```
{% ESNext %}
```js
import { registerBlockType } from '@wordpress/blocks';
import { InnerBlocks } from '@wordpress/block-editor';

registerBlockType( 'a8c/workshop-ex7', {
mkaz marked this conversation as resolved.
Show resolved Hide resolved
// ...

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

save: ( { className } ) => {
return (
<div className={ className }>
<InnerBlocks.Content />
</div>
);
},
} );
```
{% end %}

## Allowed Blocks

Using the `ALLOWED_BLOCKS` property, you can define the set of blocks allowed in your InnerBlock. This restricts the that can be included only to those listed, all other blocks will not show in the inserter.

```js
const ALLOWED_BLOCKS = [ 'core/image', 'core/paragraph' ];
//...
<InnerBlocks
allowedBlocks={ ALLOWED_BLOCKS }
/>
```


## Template

Use the template property to define a set of blocks that prefill the InnerBlocks component when inserted. You can set attributes on the blocks to define their use. The example below shows a book review template using InnerBlocks component and setting placeholders values to show the block usage.

{% codetabs %}
{% ES5 %}
```js
const MY_TEMPLATE = [
[ 'core/image', {} ],
[ 'core/heading', { placeholder: 'Book Title' } ],
[ 'core/paragraph', { placeholder: 'Summary' } ],
];

//...

edit: function( props ) {

return el(
InnerBlocks,
{
template: MY_TEMPLATE,
templateLock: "all",
}
);
},
```
{% ESNext %}
```js
const MY_TEMPLATE = [
[ 'core/image', {} ],
[ 'core/heading', { placeholder: 'Book Title' } ],
[ 'core/paragraph', { placeholder: 'Summary' } ],
];

//...

edit: () => {

return (
<InnerBlocks
template={ MY_TEMPLATE }
templateLock="all"
/>
);
},
```
{% end %}

Use the `templateLock` property to lock down the template. Using `all` locks the template complete, no changes can be made. Using `insert` prevents additional blocks to be inserted, but existing blocks can be reorderd. See [templateLock documentation](/packages/block-editor/src/components/inner-blocks#templatelock) for additional information.

### Post Template

Unrelated to `InnerBlocks` but worth mentioning here, you can create a [post template](https://developer.wordpress.org/block-editor/developers/block-api/block-templates/) by post type, that preloads the block editor with a set of blocks.

The `InnerBlocks` template is for the component in the single block that you created, the rest of the post can include any blocks the user likes. Using a post template, can lock the entire post to just the template you define.


```php
add_action( 'init', function() {
$post_type_object = get_post_type_object( 'post' );
$post_type_object->template = array(
array( 'core/image' ),
array( 'core/heading' )
);
} );
```


## Parent-Child InnerBlocks

A common pattern for using InnerBlocks is to create a custom block that will be included only in the InnerBlocks. An example of this is the Columns block, that creates a single parent block called `columns` and then creates an child block called `column`. The parent block is defined to only allow the child blocks. See [Column code for reference](https://github.com/WordPress/gutenberg/tree/master/packages/block-library/src/column).

When defining a child block, use the `parent` block setting to define which block is the parent. This prevents the block showing in the inserter outside of the InnerBlock it is defined for.

```js
export const settings = {
title: __( 'Column' ),
parent: [ 'core/columns' ],
icon,
description: __( 'A single column within a columns block.' ),
//...
}
```
6 changes: 6 additions & 0 deletions docs/manifest-devhub.json
Expand Up @@ -455,6 +455,12 @@
"markdown_source": "../docs/designers-developers/developers/tutorials/block-tutorial/generate-blocks-with-wp-cli.md",
"parent": "block-tutorial"
},
{
"title": "Nested Blocks: Using InnerBlocks",
"slug": "nested-blocks-inner-blocks",
"markdown_source": "../docs/designers-developers/developers/tutorials/block-tutorial/nested-blocks-inner-blocks.md",
"parent": "block-tutorial"
},
{
"title": "Meta Boxes",
"slug": "metabox",
Expand Down
4 changes: 3 additions & 1 deletion docs/toc.json
Expand Up @@ -86,7 +86,9 @@
{ "docs/designers-developers/developers/tutorials/block-tutorial/introducing-attributes-and-editable-fields.md": [] },
{ "docs/designers-developers/developers/tutorials/block-tutorial/block-controls-toolbar-and-sidebar.md": [] },
{ "docs/designers-developers/developers/tutorials/block-tutorial/creating-dynamic-blocks.md": [] },
{ "docs/designers-developers/developers/tutorials/block-tutorial/generate-blocks-with-wp-cli.md": [] }
{ "docs/designers-developers/developers/tutorials/block-tutorial/generate-blocks-with-wp-cli.md": [] },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about shifting the order and having the inner blocks tutorial first? The steps of the block tutorial look clearer that way (build more complex things as you advanced) and the rhythm doesn't get broken by the CLI tutorial (which isn't about things you could use to build blocks but block set up instead).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if this CLI tutorial is still up to date 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeh, I kinda want to remove the CLI suggestion. I was going to post about that in a separate PR. I'm not sure if the scaffolding that it generates is really what we want.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be worth revisiting the CLI part, even to delete it. In the meantime, I think that section fits better after the nested/inner blocks tutorial.

{ "docs/designers-developers/developers/tutorials/block-tutorial/nested-blocks-inner-blocks.md": [] }

] },
{ "docs/designers-developers/developers/tutorials/metabox/readme.md": [
{ "docs/designers-developers/developers/tutorials/metabox/meta-block-1-intro.md": [] },
Expand Down