This article will explain how I moved away from the True Metabox plugin and coded my own sidebar for a custom post type.
I need a custom post to have 2 specific meta fields. Now, I could add these as standard metaboxes, but I wanted to experiment with creating a sidebar and have the native feel of the block editor.
Note that the Block Editor Handbook explains in detail how to create a plugin sidebar, but there is no vanilla JavaScript code, and sometimes, you just don’t need the extra dependencies and hassle that React requires.
My new sidebar has a custom icon and 2 meta keys. They are relevant to my specific plugin, so I won’t go into details. Let’s build it!
First, we need to register our script and all block dependencies. In my code below, I am only using this sidebar for a custom post type, called grid_ad
. I have also posted the entire code, without any optimizations, but if we have multiple similar meta keys, we can put the register_meta
settings array into a variable, such as below:
$meta_key_settings = [
'object_subtype' => 'grid_ad', // Custom post subtype
'show_in_rest' => true, // Allow the field to be edited in the REST API
'single' => true, // Only one value per post
'type' => 'string', // Data type (string)
'sanitize_callback' => 'sanitize_text_field', // Callback to sanitize input
];
Anyway, back to the code:
/**
* Register sidebars for various post types
*
* @return void
*/
function wppd_register_sidebar() {
// Register the JavaScript file for the sidebar
wp_register_script(
'my-sidebar-js', // Script handle
plugins_url( 'assets/js/admin/sidebar.js', __FILE__ ), // Script source URL
[
'wp-plugins', // Dependencies: WordPress plugins
'wp-edit-post', // Dependencies: WordPress edit post
'wp-element', // Dependencies: WordPress element
'wp-components', // Dependencies: WordPress components
'wp-data', // Dependencies: WordPress data
]
);
// Register custom meta fields for the 'grid_ad' post type
register_meta(
'post', // Post type (in this case, 'post' is used for generic posts)
'wppd_grid_ad_position', // Meta field name
[
'object_subtype' => 'grid_ad', // Custom post subtype
'show_in_rest' => true, // Allow the field to be edited in the REST API
'single' => true, // Only one value per post
'type' => 'string', // Data type (string)
'sanitize_callback' => 'sanitize_text_field', // Callback to sanitize input
]
);
// Register another custom meta field for the 'grid_ad' post type
register_meta(
'post', // Post type
'wppd_grid_ad_columns', // Meta field name
[
'object_subtype' => 'grid_ad', // Custom post subtype
'show_in_rest' => true, // Allow the field to be edited in the REST API
'single' => true, // Only one value per post
'type' => 'number', // Data type (number)
'sanitize_callback' => 'sanitize_text_field', // Callback to sanitize input
]
);
}
// Hook into WordPress 'init' action to register the sidebar
add_action( 'init', 'wppd_register_sidebar' );
/**
* Enqueue the sidebar script for the block editor.
*/
function wppd_my_sidebar_script_enqueue() {
// Get the current screen's information
$screen = get_current_screen();
// Check if the current post type is 'grid_ad'
if ( 'grid_ad' === $screen->post_type ) {
// Enqueue the JavaScript file for the sidebar
wp_enqueue_script( 'my-sidebar-js' );
}
}
// Hook into WordPress 'enqueue_block_editor_assets' action to enqueue the sidebar script
add_action( 'enqueue_block_editor_assets', 'wppd_my_sidebar_script_enqueue' );
Next, let’s create the actual sidebar.
Introduction and Dependencies
These are all the dependencies we are going to use for our sidebar. In the future, I intend to add a slider, some checkboxes, and a dropdown.
(function (wp) {
// Import necessary dependencies from the WordPress block editor library
const registerPlugin = wp.plugins.registerPlugin;
const PluginSidebar = wp.editPost.PluginSidebar;
const el = wp.element.createElement;
const Text = wp.components.TextControl;
const withSelect = wp.data.withSelect;
const withDispatch = wp.data.withDispatch;
const compose = wp.compose.compose;
})(window.wp);
Creating a MetaBlockField
Component
let MetaBlockField = compose(
withDispatch(function (dispatch, props) {
return {
setMetaFieldValue: function (value) {
// Update the meta field value
dispatch('core/editor').editPost({
meta: { [props.fieldName]: value },
});
// Then save the post (immediately), without the need for updating the post
dispatch('core/editor').savePost();
},
};
}),
withSelect(function (select, props) {
return {
metaFieldValue: select('core/editor').getEditedPostAttribute('meta')[props.fieldName],
};
})
)(function (props) {
return el(Text, {
label: props.label,
value: props.metaFieldValue,
type: props.type, // 'text' or 'number'
onChange: function (value) {
// For number type, ensure the value is always a number or empty string
if (props.type === 'number') {
value = value === '' ? '' : Number(value);
}
props.setMetaFieldValue(value);
},
});
});
Registering the Plugin Sidebar
registerPlugin('wppd-sidebar--grid-ads', {
render: function () {
return el(
PluginSidebar,
{
name: 'wppd-sidebar--grid-ads',
icon: 'image-filter',
title: 'Property Drive',
},
el(
'div',
{ className: 'plugin-sidebar-content' },
el(MetaBlockField, {
label: 'Grid Ad Order',
fieldName: 'wppd_grid_ad_position',
type: 'text',
}),
el(MetaBlockField, {
label: 'Grid Ad Columns',
fieldName: 'wppd_grid_ad_columns',
type: 'number',
}),
)
);
},
});
That’s all!
Now I can call my 2 meta keys in my plugin (or theme):
$grid_ad_position = (int) get_post_meta( $grid_ad_id, 'wppd_grid_ad_position', true );
$grid_ad_columns = (int) get_post_meta( $grid_ad_id, 'wppd_grid_ad_columns', true );
I’m sure the code is self-explanatory