Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gutenberg - Multiple InnerBlocks in one block-type

I am trying to make custom columns block since the wordpress default used by gutenberg is not what I need.

So i have looked up how it works, its uses InnerBlocks block with a layout definition, but there is no way to specify the html tag and the class for the columns so it's useless for me.

Then I have decided to loop out columns using map, which works fine, then i added inside each column the InnerBlocks component to allow inserting other blocks to the column, but the problem is that in each column the content of InnerBlocks is shared, so I have tried to set key property for each InnerBlock and column to be unique and their content is still shared (no i am not using shared block).

It looks like gutenberg is using the same instance of InnerBlocks in each column.

I am trying to build a block type where you can add dynamically columns and into each column add "cards" with some information.

To give some idea what am i doing, here is the return of the edit function:

<section className="infonav">
            <div className="infonav__container">
                <div>
                    <button onClick={onAddBox}>{__('Add column', 'zmg-blocks')}</button>
                </div>
                <div className="infonav__row">
                    {[...new Array(columns).keys()].map((item, index) => {
                        return (
                                <div className="infonav__row__col" key={"info_cols"+index}>
                                    <div>
                                        <button onClick={onRemoveBox.bind(index)}>
                                            {__('Remove', 'zmg-blocks')}
                                        </button>
                                    </div>
                                    <InnerBlocks key={"info_boxes"+index}/>
                                </div>
                        );
                    })}
                </div>
            </div>
        </section>

Thank you

like image 873
Erik Kubica Avatar asked Jun 27 '18 22:06

Erik Kubica


People also ask

Is Block editor the same as Gutenberg?

The Gutenberg project is now known as the WordPress Block Editor in the official WordPress documentation. It's the new way to edit content in WordPress and replaces the old TinyMCE post content editor. The Block Editor can do more, too – think shortcodes, widgets, menus, and even custom fields.

How do I move blocks in Gutenberg?

Simply select the block that you wish to move and use the arrow-like buttons to move the block up or down. You can use the arrow-like buttons in the Contextual Toolbar to move the selected block up or down the document structure.


Video Answer


2 Answers

Seems like gutenberg Innerblocks can only be used once in a block

Note: A block can render at most a single InnerBlocks and InnerBlocks.Content element in edit and save respectively. To create distinct arrangements of nested blocks, create a separate block type which renders its own InnerBlocks and assign as the sole allowedBlocks type.

Source: https://github.com/WordPress/gutenberg/tree/master/packages/block-editor/src/components/inner-blocks

You need a create another custom block(for the column only) along with this block which also uses Innerblock inside it so that other blocks can be nested inside. You can make use of allowedBlocks to only allow your custom column in this block

like image 192
Swopnil Dangol Avatar answered Nov 05 '22 18:11

Swopnil Dangol


If you meant to add multiple gutenberg blocks via InnerBlock from 'block-editor' as shown below, there is no way to add multiple blocks yet:

const BLOCK_TEMPLATE = [
  ['image-slider', { width: 800, height: 400 }],
  ['menu'],
];

registerBlockType('peregrine/inner-block-demo', {

  title: 'Inner Block Demo',

  edit({ className }) {
    return (
      <div className={className}>
        <InnerBlocks
          template={BLOCK_TEMPLATE}
          templateLock="all"
        />
      </div>
    );
  },

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

Multiple inner blocks have complexities that don't seem worth the effort, and in general it either hints at a block that should be broken down into multiple simpler blocks, or with block attributes (not children). Let us know how the above suggestion work for you and we could revisit.

You can follow the discussion here: https://github.com/WordPress/gutenberg/issues/6808

But, your code looks more like adding inner elements and that is possible.

So to clarify further, what you supply to registerBlockType function is not block. A gutenberg block a graceful shortcode, something like this:

<!-- wp:image -->
<figure class="wp-block-image"><img src="source.jpg" alt="" /></figure>
<!-- /wp:image -->

Or this:

<!-- wp:latest-posts {"postsToShow":4,"displayPostDate":true} /-->

First one is called static block because it has its content in it. Second one is called dynamic block because it is self closig block and has no content. Content will be retrived from the php callback you supplied when you register your block.

Gutenberg uses React to print visual representation of the block onto editor screen. edit method on settings object should return a react element, this element will be used to produce visual representation for the block in the editor. save method also should return react element, but this element will be rendered into static html and saved into database: <figure class="wp-block-image"><img src="source.jpg" alt="" /></figure>. Now, dynamic blocks has no return element since they return null, so there is no content in them, that's is why they are self closing.

When server responds a request, it will get the content stored in the database and runs it through parser to see if it is static or dynamic block. If block is static, it has its content in itself so that content will be returned. If it is dynamic, registered callback function will be invoked and its return value will be returned.

Now, to answer your question, save and edit functions should return react element. A react element has to have single root element, but inner elements can any regular html like this one:

<div>
  <h1>Hello world</h1>
  <p>This is a sentence</p>
</div>

This is for performance reasons. DOM operations are expensive, that's is why it has single entry point into the DOM. That is why it is very fast. It has its own DOM then on, an whole tree resides in memory. React will walk through its DOM tree when a change takes place and render only changed branch, will not paint whole tree with every little change.

Important detail here is the code above looks like html but it is not, it is jsx. React can not render html directly. Jsx will be transpiled into react element by a transpiler like babel.

There is also createElement method on React which can be used to create react element. wp re-exports this method.

You can render one react element in another one. Without learning react you can never fully grasp the power or the potential of blocks. React library is not that large. Once you grasp the idea behind it you can learn it enough to be productive in a week or two.

like image 21
snnsnn Avatar answered Nov 05 '22 16:11

snnsnn