Search code examples
wordpresswordpress-gutenberggutenberg-blocks

allowed blocks for 'core/colums' innerBlocks


I have created a custom block with innerBlocks, let's call it parent block. I only allow for one kind of block inside that block, let's call it child block using the "allowedBlocks". The simple use-case is when a user wants to add the child block inside the parent block, then it all works fine. Now here is the problem: Sometimes one would need to be able to add multiple child blocks inside the parent block next to each other. For that I would love to use the core/colums block from gutenberg. The problem is, that inside that core/colums block I also only want to be able to add the child block and no other.

Is there a way to set allowedBlocks for a block inside allowedBlocks? Is there some 'global' way of saying: "all blocks inside of this block can only be one of [..., ..., ...]?"

edit: function( props ) {

return (
<InnerBlocks allowedBlocks={ [ 'my-blocks/child-block', 'core/columns' ] } />
);

}

Now can I specify which blocks can be selected in the InnerBlock core/colums ?

*I know I could just let people add multiple child inside the parent, but I want them to be structured and responsive with the colums..

My other idea would be to somehow copy the core/colums block from gutenberg and modify it, though I don't know where to find it and it wouldn't really be pretty..*


Solution

  • At present, core/column does not support passing the allowedBlocks property, although you could potentially create your own custom renderAppender for InnerBlocks as a way to limit what blocks can be added.

    Below is an alternative approach using 3 custom blocks, templates, child and parent block relationships:

    Custom Block: Contains an InnerBlock with a template that sets the custom Parent Block as the content of the Column. You could also add other core blocks within the template if desired.

    registerBlockType('my-blocks/custom-block', {
    ...
        edit: () => {
            const MY_TEMPLATE = [
                ['core/columns', { columns: 2 }, [
                    ['core/column', {}, [
                        ['my-blocks/parent-block']
                    ]],
                    ['core/column', {}, [
                        ['my-blocks/parent-block']
                    ]],
                ]]
            ];
            return (
                <InnerBlocks
                    template={MY_TEMPLATE}
                    templateLock="all"
                />
            );
         },
    
        save: () => {
            return <InnerBlocks.Content />;
        }
    });
    

    Parent Block: Contains an InnerBlock that only accepts the Child Block (or you can also add other core blocks inside allowedBlocks).

    registerBlockType('my-blocks/parent-block', {
    ...
        edit: function({className}) {
            return (
                <div className={className}>
                    <InnerBlocks allowedBlocks={['my-blocks/child-block']} />
                </div>
            );
        },
    
        save: function({className}) {
            return (
                <div className={className}>
                    <InnerBlocks.Content />
                </div>
            )
        }
    })
    

    Child Block: Can only be added to its parent, so will not appear in the Add Block inserter unless its within its Parent Block.

    registerBlockType('my-blocks/child-block', {
        ...
        parent: ['my-blocks/parent-block'],
        edit: ({ className }) => {
            return (
                <div className={className}>
                    <h3>Child Block Content</h3>
                </div>
            );
        },
    
        save: ({ className }) => {
            return (
                <div className={className}>
                    <h3>Child Block Content</h3>
                </div>
            );
        },
    });
    

    Caveats: The columns will still allow other blocks to be added after the Parent Block unless you create a custom renderAppender to alter this.

    The above example should work for your scenario as described by implementing the additional 'Custom Block' to control the allowedBlocks of InnerBlocks and support core/columns.

    Source code for core/column and core/columns: