You may have a Wood block that describes the type of wood used in a woodturning item, or a Minerals block to list the minerals used for a jewelry work. You don’t want this two blocks to be used at the same time, because jewelry is not about wood and woodturning is not about minerals, so you want a way to prevent adding one in the editor if the other is already present.
A possible solution is to make them the same block and instead distinguish them with block variants.
As an example, there is no Youtube Vimeo or TikTok block in WordPress, they’re all block variants of core/embed
. WP tells them apart based on the values of their attributes and they’re listed as if they were independent blocks, complete with their own icons, descriptions, names, etc. Their edit components can even use the same logic to customize their UI.
With this specific in mind, a generic material list block with multiple: false
would solve your problem. Set it so that it doesn’t support insertion, then create 2 block variants that do support insertion, one for wood, and one for minerals. Now you have a minerals and a wood block both listed in the inserter, only one can be inserted, and you’ve halved the code you needed to write.
Notice though, that while this gives you what you wanted/needed, it doesn’t give you what you asked for if we’re being strict.
A Super Fiddly Alternative That Does Do What You Asked For
What you literally asked for, aka the question not the problem, can sort of be done, but it’s super fiddly, and a very very bad idea. You should avoid this!
In your edit component, register both blocks again, but with the insert supports toggled. Doing this updates the block
However:
- If you get this wrong you won’t be able to insert either block without a hard refresh
- Removing the block will be precarious, you’ll need to subscribe to the core data store and watch for the blocks removal so that you can enable them both again.
- This can all be ruined by someone copy pasting or drag dropping from somewhere else.
So there is no neat and easy solution, you can approximate the proposed solution you’ve devised, but it has major flaws. The fundamental problem is that you have 2 separate blocks doing the same thing but with different content, that content should be content/attributes/child blocks/etc
A word of warning though: You might be tempted to unregister a block, then re-register it. However if there are any instances of that block the entire editor will crash the moment it’s unregistered. Unregistering is unnecessary.
A Side Note On Using Composition To Solve This
Sometimes the answer is composition, composing multiple blocks together, rather than having lots of single use monolithic blocks. A sign you’ve made this mistake is if the block has a serialised array of “items” or “things”.
Core blocks such as galleries and lists used to make this mistake and it lead to lots of problems and weirdness. Making galleries containers for image blocks, and lists containers for list-item blocks solved this while opening up lots of opportunities to filtering and extension. It also eliminated a lot of code, why build special controls for moving gallery and list items around in an array when the block UI controls do it for you?
Given the example you provided, the list of minerals, or wood could be a containing block that held “material-item” blocks, then filled in at runtime the same way query blocks or recent posts blocks are filled in. This would let you separate the source of the data too making a CPT/Taxonomy an option, or an external data source, or even manually defined values.
Child blocks also have the advantage that they can appear in multiple places, and have their own attributes UI and logic.