How to exclude Gutenberg blocks from certain post types

At first glance you might consider using the allowed_block_types filter to disable certain blocks.

PHP
plugins/pw-examples/pw-examples.php

The problem with this however is that by default the value that is passed to this filter as $allowed_blocks is boolean true, and not a list of all the registered blocks as you might expect. This is because most blocks are wholly registered on the client side via javascript rather than on the server side via PHP.

That makes this filter great for white-listing blocks, but useless for black-listing them.

Unregister a block type

As mentioned in the Gutenberg Block Filters documentation you can unregister a block type with the wp.blocks.unregisterBlockType javascript function.

PHP
plugins/pw-examples/pw-examples.php
JS
plugins/pw-examples/unregister-block.js

There are a few problems using this above method however:

  1. Not all blocks are registered at this time. (You can only guarantee the core blocks are registered, not those added via other plugins).
  2. If the post you are editing already has one of the block types you’ve unregistered you’ll get an error about the block type not existing.
  3. Some blocks types depend on others existing so you have to be careful what you unregister.

Hiding a block type from the inserter

The solution to the above problems is to hide the blocks you don’t want available to users from the inserter so they can’t be inserted in to posts.

The core Columns block type makes use of this feature. You may not be aware but there is also a Column block type that isn’t available to be inserted manually; this block is programmatically inserted as a child of the main Columns block. The code to register a block like that goes something along the lines of the following.

JS
column.js

By default, all blocks will appear in the Gutenberg inserter. To hide a block so that it can only be inserted programmatically, set inserter to false.

WordPress.org documentation on the supports option when registering a block type.

Luckily there is a javascript registerBlockType filter for the registerBlockType function which will allow us to forcibly set inserter to false for any block we choose.

PHP
plugins/pw-examples/pw-examples.php
JS
plugins/pw-examples/filter-register-block-type.js

Creating a disallowed_block_types filter

Bringing everything above together we can create a disallowed_block_types filter that functions similarly to the built in allowed_block_types filter; allowing us to black-list blocks on the server/PHP side with full knowledge of the post (and therefore post type) being edited.

PHP
plugins/pw-examples/pw-examples.php

We can then use the disallowed_block_types filter we’ve created just as we would the built-in allowed_block_types one.

PHP
plugins/pw-examples/pw-examples.php

As we have access to the $post object we can also conditionally remove block types e.g. based on the post type.

PHP
plugins/pw-examples/pw-examples.php