Search code examples
reactjswordpress-gutenberg

Is there a way to know in the parent block that you are editing an inner block of that parent?


The props.isSelected of a parent block is true only when you are inside the parent block but not when you are editing inside the innerBlocks of that blocks.

How can I check, from the parent block, if the user is editing an inner block of this parent (no matter how deep)

I'm asking because I want to do some kind of a toggle functionality for the innerBlocks of the parent, to not be visible until you select the parent Block and tried using props.isSelected but obviously when you start editing an inner block it immediately disappears because the parent is not selected anymore

Here is a simple code that should demonstrate what I'm talking about

registerBlockType('test/parent', {
    name: 'Parent',
    edit: (props) => {
      const template = [['test/child'],['test/child']];
      if (props.isSelected) {
        return <InnerBlocks template={template}/>;
      }
      return <div>Click me to see my inner block</div>;
    },
    save: (props) => {
        return <InnerBlocks.Content />;
    }
};
registerBlockType('test/child', {
    name: 'Child',
    parent: ['test/parent'],
    edit: (props) => {
      return <div>I'm the child I can have some more nested blocks but if you click on me I will be gone because my parent won't want me anymore, I wish somebody could edit me :(</div><InnerBlocks />;
    },
    save: (props) => {
        return <div>I'm the child</div><InnerBlocks.content />;
    }
}

Solution

  • After quite a lot of research I made my own function to determine if an inner block is selected or not (requires wp-data)

    Here is the code

    registerBlockType('test/parent', {
        name: 'Parent',
        edit: (props) => {
            const template = [['test/child'],['test/child']];
            if (props.isSelected || hasSelectedInnerBlock(props)) {
                return <InnerBlocks template={template}/>;
            }
            return <div>Click me to see my inner block</div>;
        },
        save: (props) => {
            return <InnerBlocks.Content />;
        }
    };
    
    function hasSelectedInnerBlock(props) {
        const select = wp.data.select('core/editor');
        const selected = select.getBlockSelectionStart();
        const inner = select.getBlock(props.clientId).innerBlocks;
        for (let i = 0; i < inner.length; i++) {
            if (inner[i].clientId === selected || inner[i].innerBlocks.length && hasSelectedInnerBlock(inner[i])) {
                return true;
            }
        }
        return false;
    };