Before we have a chance to include content in our sidebar besides a “Hello World”, we need to assume a few things.
Let’s get started by adding a sidebar.js
file in our src folder like so:
.
└── landing-page-gutenberg-template/
├── dist/
│ ├── sidebar.js (compiled JS)
│ └── template.css (compiled SCSS)
└── src/
└── js/
├── index.js
└── sidebar.js
Code language: AsciiDoc (asciidoc)
We’ll need a few dependencies to get this sidebar up and running. We’ll be using React hooks to set up our initial state, read in the saved meta values, and saving them as soon as the post has been updated.
const { __ } = wp.i18n;
const { Fragment, useState, useEffect } = wp.element;
const {
PanelBody,
PanelRow,
ToggleControl,
} = wp.components;
const { withDispatch } = wp.data;
const { PanelColorSettings } = wp.blockEditor;
Code language: JavaScript (javascript)
The main things you may recognize is the useState
and useEffect
React hooks. We’ll be using those to set a default state also read in the stored meta values.
const Sidebar = (props) => {
const [enabled, setEnabled] = useState(false);
const [bodyColor, setBodyColor] = useState(false);
Code language: JavaScript (javascript)
We start off by setting the initial state of two variables we’ll be using for state: enabled
and bodyColor
. We’ll set these two to false as they are unused if nothing is selected.
Next, we’ll use useEffect
to initialize our state variables.
/* Initialize the initial state */
useEffect(() => {
const {
_wpajax_enable_landing_template,
_wpajax_set_body_color,
} = wp.data.select("core/editor").getEditedPostAttribute("meta");
if (
_wpajax_enable_landing_template != null &&
_wpajax_enable_landing_template.length != 0
) {
setEnabled(_wpajax_enable_landing_template);
} else {
setEnabled(false);
}
if (_wpajax_set_body_color != null && _wpajax_set_body_color.length != 0) {
setBodyColor(_wpajax_set_body_color);
} else {
setBodyColor("");
}
}, []);
Code language: JavaScript (javascript)
We grab the meta names by variable name (meta key name) and check if they are set or not. If they are set, then we re-set state to what is stored at the post level.
The sidebar components will consist of a toggle control and a color picker.
return (
<Fragment>
<PanelBody title={__('Landing Template', 'landing-page-gutenberg-template')}>
<PanelRow>
<ToggleControl
label={__(
"Enable Landing Page Template",
"landing-page-gutenberg-template"
)}
checked={enabled}
onChange={(value) => {
props.setMetaFieldValue("_wpajax_enable_landing_template", value);
setEnabled(value);
}}
/>
</PanelRow>
{enabled && (
<Fragment>
<PanelRow>
<PanelColorSettings
title={ __( 'Colors', 'landing-page-gutenberg-template' ) }
initialOpen={ true }
colorSettings={ [ {
value: bodyColor,
onChange: ( value ) => {
props.setMetaFieldValue("_wpajax_set_body_color", value);
setBodyColor(value);
},
label: __( 'Select a Body Background Color', 'landing-page-gutenberg-template' ),
} ] }
/>
</PanelRow>
</Fragment>
)}
</PanelBody>
</Fragment>
);
};
Code language: JavaScript (javascript)
When we have an on-change event, we call a prop function called setMetaFieldValue
. We’ll use a fancy WordPress trick to be able to access the post meta to tell WordPress to save our meta and/or record a change so the user is alerted that navigating away from the page will result in lost data.
export default withDispatch((dispatch) => {
return {
setMetaFieldValue: function (key, value) {
dispatch("core/editor").editPost({ meta: { [key]: value } });
},
};
})(Sidebar);
Code language: JavaScript (javascript)
Here is the entire sidebar.js
file as a matter of reference.
const { __ } = wp.i18n;
const { Fragment, useState, useEffect } = wp.element;
const {
PanelBody,
PanelRow,
ToggleControl,
} = wp.components;
const { withDispatch } = wp.data;
const { PanelColorSettings } = wp.blockEditor;
const Sidebar = (props) => {
const [enabled, setEnabled] = useState(false);
const [bodyColor, setBodyColor] = useState(false);
/* Initialize the initial state */
useEffect(() => {
const {
_wpajax_enable_landing_template,
_wpajax_set_body_color,
} = wp.data.select("core/editor").getEditedPostAttribute("meta");
if (
_wpajax_enable_landing_template != null &&
_wpajax_enable_landing_template.length != 0
) {
setEnabled(_wpajax_enable_landing_template);
} else {
setEnabled(false);
}
if (_wpajax_set_body_color != null && _wpajax_set_body_color.length != 0) {
setBodyColor(_wpajax_set_body_color);
} else {
setBodyColor("");
}
}, []);
return (
<Fragment>
<PanelBody title={__('Landing Template', 'landing-page-gutenberg-template')}>
<PanelRow>
<ToggleControl
label={__(
"Enable Landing Page Template",
"landing-page-gutenberg-template"
)}
checked={enabled}
onChange={(value) => {
props.setMetaFieldValue("_wpajax_enable_landing_template", value);
setEnabled(value);
}}
/>
</PanelRow>
{enabled && (
<Fragment>
<PanelRow>
<PanelColorSettings
title={ __( 'Colors', 'landing-page-gutenberg-template' ) }
initialOpen={ true }
colorSettings={ [ {
value: bodyColor,
onChange: ( value ) => {
props.setMetaFieldValue("_wpajax_set_body_color", value);
setBodyColor(value);
},
label: __( 'Select a Body Background Color', 'landing-page-gutenberg-template' ),
} ] }
/>
</PanelRow>
</Fragment>
)}
</PanelBody>
</Fragment>
);
};
export default withDispatch((dispatch) => {
return {
setMetaFieldValue: function (key, value) {
dispatch("core/editor").editPost({ meta: { [key]: value } });
},
};
})(Sidebar);
Code language: JavaScript (javascript)
Now that we have working sidebar innards (in theory), let’s go back to index.js and place all the placeholders into place and get rid of our “Hello World.”
Code language: JavaScript (javascript). └── landing-page-gutenberg-template/ ├── dist/ │ ├── sidebar.js (compiled JS) │ └── template.css (compiled SCSS) └── src/ └── js/ ├── index.js └── sidebar.js
import Sidebar from "./sidebar";
const { __ } = wp.i18n;
const { registerPlugin } = wp.plugins;
const { PluginSidebar, PluginSidebarMoreMenuItem } = wp.editPost;
const { Fragment } = wp.element;
registerPlugin("landing-page-gutenberg-template", {
icon: (
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 0 24 24"
width="24"
>
<path d="M0 0h24v24H0z" fill="none" />
<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" />
</svg>
),
render: () => {
return (
<Fragment>
<PluginSidebarMoreMenuItem target="landing-page-sidebar">
{__("Landing Page", "anding-page-gutenberg-template")}
</PluginSidebarMoreMenuItem>
<PluginSidebar
name="landing-page-sidebar"
title={__("Full Width", "anding-page-gutenberg-template")}
>
<Sidebar />
</PluginSidebar>
</Fragment>
);
},
});
Code language: JavaScript (javascript)
We finally have a working Gutenberg sidebar. What’s left to do?
Let’s concentrate on how to read in this saved post meta and do something with it such as loading a landing page template.