How to Register Meta Fields in Gutenberg

Pre-requisites

  • WordPress Plugin Development
  • PhP
  • JS/ReactJS
  • Hands on experience in Gutenberg block development

Example Scenario

Consider a scenario where a client asks you to develop a functionality. The functinoality includes showing a sub-title of the given page. The sub-title will be content managed and author can decide whether to show/hide that sub-title on the front-end. Hence we need to register 2 meta fields for ‘Page’ post type. This means, we need to show 2 fields in sidebar when page is being edited. Those fields are as follows:

  • Sub-title – A simple text field which stores a sub-title associated with page
  • Hide sub-title – A boolean checkbox field which will decide to hide/show the sub-title.

Register Custom Meta

First of all, we need to ensure that custom meta is registered for the given post type. This helps in Gutenberg APIs while updating the meta-value on saving the post. You can use register_post_meta function for the same. Find the PhP code below.

<?php

/**
* Function registers the custom meta required for'page' post type.
*
* @return void
*/
function register_post_meta_callback() {
    //register meta for 'sub-title'
    register_post_meta(
        'page',
        'custom_page_sub_title',        //this will become post-meta key
        array(
            'show_in_rest'  => true,
            'single'        => true,
            'type'          => 'string',
            'auth_callback' => function() {
                    return current_user_can( 'edit_posts' );
            }
        )
    );
    
    // Register meta for 'sub-title' show/hide
    register_post_meta(
        'page',
        'custom_page_enable_sub_title',        //this will become post-meta key
        array(
            'show_in_rest'  => true,
            'single'        => true,
            'type'          => 'boolean',
            'auth_callback' => function() {
                    return current_user_can( 'edit_posts' );
            }
        )
    );
}
add_action('init', 'register_post_meta_callback');

Add the fields in the Gutenberg

Now, it’s the time where you are actually using this registered meta in the Gutenberg editor. Please see the code below:

/**
 * Page Subtitle Panel
 */

const {
	data: { useSelect, useDispatch },
	plugins: { registerPlugin },
	element: { useState, useEffect, Fragment },
	components: { TextControl },
	i18n: { __ },
	domReady,
} = wp;
const { PluginDocumentSettingPanel } = wp.editPost || {};
const { ToggleControl } = wp.components;

/**
 * Page Subtitle Panel
 */
function PageSubTitle() {
	if (!PluginDocumentSettingPanel) {
		return null;
	}

	// Let's fetch the data from existing post meta and set constact values with same meta keys
	const {
		meta,
		meta: {
			custom_page_sub_title,
			custom_page_enable_sub_title
		},
	} = useSelect((select) => ({
		meta: select('core/editor').getEditedPostAttribute('meta') || {},
	}));

	const { editPost } = useDispatch('core/editor');

	// States/Attributes in terms of holding meta values
	const [subTitle, setSubtitle ] = useState( custom_page_sub_title );
	const [enableSubTitle, setEnableSubtitle ] = useState( custom_page_enable_sub_title );

	//Instantiating the states with post meta values
	useEffect(() => {
		editPost( {
			meta: {
				...meta,
				custom_page_sub_title: subTitle,
				custom_page_enable_sub_title: enableSubTitle,
			},
		} );
	}, [subTitle, enableSubTitle]);

	return (
		<PluginDocumentSettingPanel
			name="page-subtitle-settings-panel"
			title={ __( 'Page Subtitle', 'vyawtech' ) }
		>
			{/* The Subtitle Control - Start */}
			<TextControl
				value={ subTitle }
				onChange={ setSubtitle }
				type="string"
				placeholder="Sub-title of Page"
				label={
					__( 'Subtitle', 'vyawtech' )
				}
			/>
			{/* The Subtitle Control - End */}

			{/* The hide/show Toggle Control - Start */}
			<ToggleControl
				checked={ enableSubTitle }
				onChange={ ( newEnablePageSubtitle ) => {
					setEnableSubtitle( newEnablePageSubtitle );
					editPost( {
						meta: {
							...meta,
							[ custom_page_enable_sub_title ]: newEnablePageSubtitle,
						},
					} );
				} }
				label={
					__( 'Hide Subtitle', 'vyawtech' )
				}
			/>
			{/* The hide/show Toggle Control - End */}
		</PluginDocumentSettingPanel>
	);
}

if ( 'page' === window.pagenow ) {					// Enabling only for 'page' post type
	registerPlugin( 'page-subtitle-settings', {
		render: PageSubTitle,
		icon: false,
	});
}

Now register above component in your blocks.js file as shown below

import './sidebar/page-sub-title';

Now register the JS file in block assets so that it will register your Gutenberg block assets.

/**
 * Enqueue editor-only JavaScript/CSS for blocks.
 *
 * @return void
 */
function block_editor_scripts() {

	// Editor Scripts
	wp_enqueue_script(
		'vyawtech-editor',
		VYATECH_URL . 'dist/js/blocks.js',
		[ 'wp-i18n', 'wp-element', 'wp-blocks', 'wp-components', 'wp-editor', 'wp-dom', 'wp-compose', 'wp-plugins', 'wp-core-data', 'wp-edit-post' ],
		VYAWTECH,
		true
	);
}
add_action( 'enqueue_block_editor_assets', 'block_editor_scripts' );

Final Results


The custom meta-box appearing on edit page

The custom meta-box using Gutenberg Editor

The database entries of the same post

The database entries showing custom meta data updated through Gutenberg