I'm inserting a block programmatically and I want to prevent users from removing it. Is there any way to disable the "Remove Block" option for a specific block?
Hey @woorise! There's no API that lets third parties disable the _Remove Block_ option for a specific block.
There is, however, Templates which lets you specify which blocks should be in a post by default and lock them down so that the user can't add/remove any further blocks.
Does that cover your use case? If not, could you go into some detail on what you're trying to accomplish?
I tried the Templates and more specifically the PHP locking snippet with the "insert" option to lock a specific block but it doesn't allow me to insert any other block (different type).
Is this the default behavior?
Yes that's right, template locking prevents both insertion and deletion.
I don't think it makes sense to allow one without the other. For example, if a user can insert blocks but not delete them, how can they remove blocks that are accidentally inserted?
Could you go into some detail on what you're trying to accomplish?
Template locking prevents insertion and deletion for a specific block or for all blocks?
These are my requirements:
Thanks for the extra info, @woorise!
Right now a developer can prevent the user from inserting and deleting _all_ blocks using template locking, but it is not possible to disable inserting and deleting _a specific_ block.
Potentially we could do this by adding supports.remove
to the block configuration. This would mirror supports.inserter
.
Great! This would be a highly welcomed addition.
If you want to make sure that you can't remove a specific block (myplugin/important-block
), you could do something like this:
const getBlockList = () => wp.data.select( 'core/block-editor' ).getBlocks();
let blockList = getBlockList();
wp.data.subscribe( () => {
const newBlockList = getBlockList();
if (
newBlockList.length < blockList.length
&& blockList.some( block => block.name === 'myplugin/important-block' ) )
&& newBlockList.every( block => block.name !== 'myplugin/important-block' )
) {
wp.data.dispatch( 'core/block-editor' ).resetBlocks( blockList );
}
blockList = newBlockList;
} );
This code will make sure that at least one block with the name myplugin/important-block
will be present in the editor.
Also check: https://bdwm.be/gutenberg-prevent-specific-block-from-being-removable/
@pwkip Thanks for the workaround. But still, it would be nice to have some officially supported block setting for that.
Btw I think that in your fix might be an issue with nested blocks. Some block (e.g. core/columns
OR core/column
) may carry other blocks on innerBlocks
property. blockList.some
and blockList.every
check only the top level so you may miss the myplugin/important-block
if it is inside a column or some other block that support nested blocks.
You can use this function for searching for a block.
const findBlock = (blocks, name) => (
blocks.reduce((result, block) => {
if (result) {
return result;
}
if (block.name === name) {
return block;
}
if (Array.isArray(block.innerBlocks) && block.innerBlocks.length) {
return findBlock(block.innerBlocks, name);
}
return null;
}, null)
);
Most helpful comment
Great! This would be a highly welcomed addition.