I couldn’t find a standard way to do this, but as I commented, an easy way to do it is by using a state which will store either the initial template you set or the inner blocks (i.e. their names and attributes) that were already added to the parent block. Which basically means, you will pass conditional template
to the InnerBlocks
component.
Working Example
-
WordPress dependencies specific to this example, in addition to
InnerBlocks
etc.import { useSelect } from '@wordpress/data'; import { useState } from '@wordpress/element'; import { Button } from '@wordpress/components'; // for the demos; see below
-
Now here’s the
edit()
function where I added 2 buttons for testing the functionality you wanted to have:function edit( { clientId } ) { const innerBlocks = useSelect( select => { const { getBlocks } = select( 'core/block-editor' ); return getBlocks( clientId ); }, [ clientId ] ); // If there are no inner blocks yet, use the initial template. Else, we use // the name and attributes of each (immediate) child block. const _template = ( innerBlocks.length < 1 ) ? MY_TEMPLATE : innerBlocks.map( block => [ block.name, block.attributes ] ); // Add a state which ensures React re-renders our block when the template is // changed. const [ template, setTemplate ] = useState( _template ); // Demo callback which adds a child block. const demoInsertChildBlock = () => // wrapped setTemplate( [ ...template, [ 'core/quote', {} ] ] ); // Demo callback which removes a child block. const demoRemoveChildBlock = () => { const newTemplate = [ ...template ]; // copy current template newTemplate.pop(); // remove the last child setTemplate( newTemplate ); }; return ( <div { ...useBlockProps() }> Hello from the editor! <InnerBlocks template={ template } templateLock="all" /> <Button text="Insert demo block" variant="primary" onClick={ demoInsertChildBlock } /> <span> </span> <Button text="Remove last block" variant="primary" onClick={ demoRemoveChildBlock } /> </div> ); }
So as you could see, you just need to call
setTemplate()
function to add/remove a child block.