The Block API of Gutenberg supports post meta as a attribute source . But what if you want to use post meta in say a plugin sidebar?
With the help of the @wordpress/data package and so called “higher-order components ” it’s as easy as for blocks. 🙌
First we import all the required dependencies. This assumes that you’re using webpack and define your externals like this . If you’re looking for an ES5 example take a look at the block editor handbook .
/**
* WordPress dependencies
*/
import {
withSelect ,
withDispatch ,
} from '@wordpress/data' ;
import {
PluginSidebar ,
PluginSidebarMoreMenuItem ,
} from '@wordpress/edit-post' ;
import {
PanelColor ,
} from '@wordpress/editor' ;
import {
Component ,
Fragment ,
compose ,
} from '@wordpress/element' ;
import { __ } from '@wordpress/i18n' ;
import { registerPlugin } from '@wordpress/plugins' ;
To render the UI we extend Component
and implement the render()
method. For this example I used a PanelColor
component which allows a user to select a color. We’ll save the hex value in the post meta my_color_one
:
/**
* Custom component with a simple color panel.
*/
class MyPlugin extends Component {
render () {
// Nested object destructuring.
const {
meta : {
my_color_one : colorOne ,
} = {},
updateMeta ,
} = this . props ;
return (
< Fragment >
< PluginSidebarMoreMenuItem
name = "my-plugin-sidebar"
type = "sidebar"
target = "my-plugin-sidebar"
>
{ __ ( 'Color it!' , 'my-plugin' ) }
< /PluginSidebarMoreMenuItem>
< PluginSidebar
name = "my-plugin-sidebar"
title = { __ ( 'Color it!' , 'my-plugin' ) }
>
< PanelColor
colorValue = { colorOne }
initialOpen = { false }
title = { __ ( 'Color 1' , 'my-plugin' ) }
onChange = { ( value ) => {
// value is undefined if color is cleared.
updateMeta ( { my_color_one : value || '' } );
} }
/>
< /PluginSidebar>
< /Fragment>
);
}
}
(Please ignore the incorrect syntax highlighting.)
Now we need a higher-order component which is used to fetch the data , in this case our post meta.
// Fetch the post meta.
const applyWithSelect = withSelect ( ( select ) => {
const { getEditedPostAttribute } = select ( 'core/editor' );
return {
meta : getEditedPostAttribute ( 'meta' ),
};
} );
The second higher-order component is used to update the data .
// Provide method to update post meta.
const applyWithDispatch = withDispatch ( ( dispatch , { meta } ) => {
const { editPost } = dispatch ( 'core/editor' );
return {
updateMeta ( newMeta ) {
editPost ( { meta : { ... meta , ... newMeta } } ); // Important: Old and new meta need to be merged in a non-mutating way!
},
};
} );
Since we now have two higher-order components we have to combine them with compose
:
// Combine the higher-order components.
const render = compose ( [
applyWithSelect ,
applyWithDispatch
] )( MyPlugin );
Having a fully renderable component we can finally register our custom plugin:
registerPlugin ( 'my-plugin' , {
icon : 'art' ,
render ,
} );
And that’s it! 🚢
PS: Make sure to register the post meta properly with 'show_in_rest' => true
.
Photo by Kimberly Farmer .