Additional fields in the Gutenberg WordPress editor

Edward Bock
Write better WordPress code
5 min readOct 1, 2021

There are several fields you can use to create your posts, such as title, excerpt, content, author and taxonomy terms which come with a standard user interface. But sometimes this is not enough and you want to add more meta information about your post.

This article shows different possibilities to extend the Gutenberg UI and how to persist your data.

So let’s add an input field to save the reading time of a post. I wrote an article about how to do this with the post meta box in classic WordPress editor. The post meta box approach still works with Gutenberg and you can certainly use the code from the article I mentioned, but you shouldn’t do it this way. The recommendation is to extend the post rest response and add react components for the Gutenberg UI. So let’s dive into code.

Server-side

Depending on where you want to store your reading time value, you have two implementation options. The simplest is to use register_post_meta.

This code will register a post meta reading_time for the post type post . The post meta will be a single value so there will not be multiple reading_time meta values for single post and the datatype is numeric. It is very important to add a truthy value for show_in_rest which will extend the post responses of the rest api by our new field “reading_time”.

ALTERNATIVELY (do not use both for the same key!) you can use register_rest_field. With this approach you can use another data source then post meta.

First argument is the post types to work on and second is the field key in the post rest json response. The third parameter needs a litte more configuration. With get_callback and update_callback you have to implement reading from and writing to your custom data source. The schema property is metadata about how your fields data is structured. It provides an easy way to validate data. In this case only allow integer values that are greater than or equal to 0 are allowed.

If you want to read more about the reading time database have a look at this article: https://medium.com/write-better-wordpress-code/do-not-use-post-meta-fec12a7661

This is all you have to do in PHP code. Everything else will be done in the JavaScript.

Client-side

The backend is ready. You can find the new field reading_time in the post api response and in the redux store of Gutenberg. Now it’s to write some JavaScript code.

The following code examples will use modern JavaScript with jsx. If you are unsure how to configure a module bundler to transpile it to browser readable JavaScript code, please have a look at wordpress/scripts.

Reading time state hook

If you’re familiar with React, you probably know about state hooks. You can use a custom state hook to encapsulate logic from your ui component. When implementing a custom state hook, try to always use the same function signature as React’s useState. Implementing a state hook to get and set the reading time might look something like this.

The first function useReadingTime is a custom hook. In its scope are two other hooks useSelect and useDispatch that provide access to the the Gutenberg editor’s Redux stores. Use selectReadingTime to select the reading time value from the core/editor store. After you get the core/editor dispatcher object, it’s pretty easy to set a new reading time value by as using the editPost function of the dispatcher objects.

The client-side code for accessing the data is ready. Let’s finally move on to the user interface.

You can install the @wordpress/data npm package which will help you with autocompletion support. And if you properly added the Gutenberg JavaScript dependency management of wordpress packages will automatically be handled for you.

User interface

There are at least three slots where you can insert the new user interface component.

(1) For simple meta information related to the post’s status or visibility, you can use the PluginPostStatusInfo slot. This could be the right place for the reading time input field.

(2) For meta information that needs a litte more space for configuration or that can be considered as a separate set of topics, you can use the PluginDocumentSettingPanel slot. These panels have a title and their content is collapsible to avoid cluttering the user interface. If you don’t want every post to have a reading time, you could consider using this slot as it is still highly visible but less intrusive.

(3) If you want to display a large amount of information that doesn’t always need to be visible, the PluginSidebar provides plenty of space for your data. In my opinion, this slot would not be suitable for this use case, but we will implement it anyways for demonstration purposes.

(1) PostStatusInfo

To add an input field to the PostStatusInfo slot, we have to use three packages.

  • @wordpress/plugins for plugin registration
  • @wordpress/edit-post for the component that helps us find the right slot
  • @wordpress/components for Gutenberg user interface components (The use of the components package is optional but recommended)

Register a new plugin with the registerPlugin function, obviously. Its first parameter is a unique plugin name and the second is a configuration object for the plugin. In our case, the only required attribute of this configuration is a render function that will be used to render the user interface.

To add a user interface to the PostStatusInfo slot, use the PluginPostStatusInfo component. In this case, the only user interface is a TextControl component that gets and sets state with the custom hook useReadingTime.

That’s it. A new input field in the PostStatusInfo slot should be visible and its value should be saved.

(2) DocumentSettingPanel

If you use the PluginDocumentSettingPanel component instead of thePluginPostStatusInfo component, the new user interface appears as a collapsible panel. The rest of the code remains unchanged.

(3) Sidebar

For a sidebar we need to add two components. The PluginSidebarMoreMenuItem will add a menu item to the menu, accessible via the three dots in the upper right corner. The PluginSidebar will render the input field. The target property of the menu item component must match the name property value of the sidebar so it can open the sidebar when clicked.

Final words

That’s it! You can now extend Gutenberg UI with new input fields. Just be careful if you use custom post types in your system. It could break the editor if you register a field only for some post types and don’t check in your JavaScript code if the currently edited post is supporting the field.

If you have any objections, additions, or questions you would like me to answer in future articles, feel free to leave a comment.

--

--