Native Meta Fields UI in the Block Editor

Many digital agencies use the Advanced Custom Fields (ACF) plugin to handle custom meta fields in WordPress. In this tutorial, we are showcasing how to work with custom meta fields data in the block editor – without any plugins!

Adding custom post types and custom fields on your WordPress site lets you add and show extra information that doesn’t fit into the pre-existing sections. This is especially useful in managing the kind of content that is relevant to your site.

Native Meta Fields Example

So, how to add meta fields without plugins in WordPress? Our goal here is to use the native functionality in WordPress to provide three meta fields for a custom post type. In our example, we’ll handle information about offices, containing the following fields:

  • Email
  • Phone
  • URL

Three steps are required to make this work:

  1. Register the custom post type
  2. Register post meta
  3. Register custom UI in the block editor document settings panel

End result will look like this in the block editor settings sidebar:

Meta fields with email, phone and URL.

Register the Custom Post Type

Let’s register the “office” custom post type by using register_post_type function. Note that the custom post type needs to support custom-fields, so we’ll include that. Otherwise the meta fields data will not be connected to the REST API.

register_post_type( 'office', array(
   ...
   // Add support for custom-fields
   'supports' => array( 'title', 'editor', 'custom-fields', ),
   ...
) );

Also, set show_in_rest to true for the post type to be available in the block editor.

See full code example for registering custom post type can be seen in GitHub.

Register Post Meta

Next, we’ll register post meta by using the register_post_meta function. Set show_in_rest to true for the post meta to be available in the REST API.

Here is an example registering an office_email meta field:

register_post_meta(
  'office',
  'office_email',
  array(
    'type'              => 'string',
    'description'       => 'Email address of the office',
    'single'            => true,
    'show_in_rest'      => true,
    'sanitize_callback' => 'sanitize_email',
    'auth_callback'     => function ( $allowed, $meta_key, $post_id, $user_id ) {
      // Allows anyone who can edit this post
      return current_user_can( 'edit_post', $post_id );
    },
  )
);

Note that parameters sanitize_callback and auth_callback are important for security.

See full code example for registering post meta in GitHub.

Register Custom UI in the Block Editor Document Settings Panel

Lastly, we need to register custom UI for meta data. Thanks to Ryan Welcher, there is a really good example how to do this using Javascript and WordPress components.

In order to expose our custom UI in the settings sidebar, we’ll use the SlotFills component.

  1. Import the registerPlugin method from the @wordpress/plugins package.
  2. Import the PluginDocumentSettingPanel from the @wordpress/editor package.
  3. Use useSelect to get current post type and post ID from the editor store.
  4. Use useEntityProp to get and update post meta.
  5. Use needed components inside the PluginDocumentSettingPanel, like TextControl to build the UI.
  6. Register the plugin.

Get Information from the Editor Store

From the editor store, we want to get…

  1. current post type: based on this info, we can expose our UI in wanted post types.
  2. current post ID: based on this info, we can get and update post meta in the current post.

Here is an example of how to get the data we want:

import {
  store as editorStore,
} from '@wordpress/editor';

const { currentPostType, currentPostId } = useSelect( ( select ) => { // eslint-disable-line
  return {
    currentPostType: select( editorStore ).getCurrentPostType(),
  currentPostId: select( editorStore ).getCurrentPostId(),
  };
}, [] );

Now we can for example check in which post type we want to expose our UI:

if ( currentPostType !== 'office' ) {
  return null;
}

Get and Update Post Meta

useEntityProp hook provides meta values and method for updating the meta.

const [ meta, setMeta ] = useEntityProp( // eslint-disable-line
  'postType',
  currentPostType,
  'meta',
  currentPostId
);

After that we can use for example TextControl component for office email UI (office_email meta key):

<TextControl
  label={ __( 'Email', 'example-dynamic' ) }
  value={ meta?.office_email }
  onChange={ ( office_email ) => {
    setMeta( { ...meta, office_email } );
  } }
  __next40pxDefaultSize
/>

Repeat the similar approach for other meta values.

Wrapping All the Code for the UI

As a reminder, end result should look like this in the block editor settings sidebar:

Meta fields with email, phone and URL.

See full code example for the UI in GitHub.

What’s Next?

Thank you for reading! Now you know how to register a custom post type in WordPress, how to register post meta, and how to register a custom user interface to showcase your new custom data, all with native functionalities found in WordPress.

In the upcoming articles, we’ll demonstrate how to use meta data using Block Bindings API.