I’m trying to add a custom color control to the group and cover blocks, and if a color is selected, construct a custom className for the block. This won’t be used for the default text color or background color.
What I’ve done:
- I have filtered
blocks.registerBlockType
and added the custom
attribute. - I’ve made the function to filter
editor.BlockEdit
properly and add aPanelColorSettings
control to the group and
cover blocks only. - I have filtered
blocks.getSaveContent.extraProps
to add the custom class on save.
I’ve been able to get the control to appear, and the className to save to the block when saving the post properly. On the front end, it works.
What’s missing:
The problem I’m having is that the className only applies on save, so if I cycle through all colors in the editor, the className isn’t applied live in the editor, so I can’t see the changes on the fly.
What I think the problem is:
I’m using a filter to save the custom className on save, but there’s nothing I can find for how to do it on the fly in the editor.
My code (updated):
/**
* External Dependencies
*/
import classnames from 'classnames';
/**
* WordPress Dependencies
*/
const { __ } = wp.i18n;
const { addFilter } = wp.hooks;
const { Fragment } = wp.element;
const { createHigherOrderComponent } = wp.compose;
const { InspectorControls, getColorObjectByColorValue, PanelColorSettings } = wp.blockEditor;
const { select } = wp.data;
// Restrict to specific block names
const allowedBlocks = ['core/group', 'core/cover'];
/**
* Add custom attribute for section separator.
*
* @param {Object} settings Settings for the block.
*
* @return {Object} settings Modified settings.
*/
function addAttributes(settings) {
//check if object exists for old Gutenberg version compatibility
//add allowedBlocks restriction
if (typeof settings.attributes !== 'undefined' && allowedBlocks.includes(settings.name)) {
settings.attributes = Object.assign(settings.attributes, {
dividerColor: {
type: 'string',
default: null,
}
});
}
return settings;
}
/**
* Add section divider controls on Advanced Block Panel.
*
* @param {function} BlockEdit Block edit component.
*
* @return {function} BlockEdit Modified block edit component.
*/
const withAdvancedControls = createHigherOrderComponent((BlockEdit) => {
return (props) => {
if (!allowedBlocks.includes(props.name)) {
return(<BlockEdit {...props} />);
}
const {
name,
attributes,
setAttributes,
isSelected,
} = props;
const {
dividerColor
} = attributes;
const changeColor = (value) => {
setAttributes({ dividerColor: value });
console.log(props);
}
return (
<Fragment>
<BlockEdit {...props} />
{isSelected && allowedBlocks.includes(name) &&
<InspectorControls>
<PanelColorSettings
title={__('Section Divider')}
colorSettings={[
{
value: dividerColor,
onChange: changeColor,
label: __('Choose a color to enable the divider.')
}
]}
/>
</InspectorControls>
}
</Fragment>
);
};
}, 'withAdvancedControls');
/**
* Add custom element class in save element.
*
* @param {Object} extraProps Block element.
* @param {Object} blockType Blocks object.
* @param {Object} attributes Blocks attributes.
*
* @return {Object} extraProps Modified block element.
*/
function applyExtraClass(extraProps, blockType, attributes) {
const { dividerColor } = attributes;
//check if attribute exists for old Gutenberg version compatibility
//add class only when dividerColor is not empty
//add allowedBlocks restriction
if (typeof dividerColor !== 'undefined'
&& dividerColor
&& allowedBlocks.includes(blockType.name)) {
const settings = select('core/editor').getEditorSettings();
const colorObject = getColorObjectByColorValue(settings.colors, dividerColor);
if (colorObject) {
extraProps.className = classnames(extraProps.className, 'divider divider-' + colorObject.slug);
}
}
return extraProps;
}
/**
* Add size class to the block in the editor
*
* @param {Object} BlockListBlock BlockListBlock object.
*
* @return {Object} Modified BlockListBlock object.
*/
const addDividerClass = createHigherOrderComponent((BlockListBlock) => {
return (props) => {
const {
attributes,
className,
name,
} = props;
const { dividerColor } = attributes;
if (!allowedBlocks.includes(name)) {
return <BlockListBlock {...props} />;
}
const settings = select('core/editor').getEditorSettings();
const colorObject = getColorObjectByColorValue(settings.colors, dividerColor);
if (!colorObject) {
return <BlockListBlock {...props} />;
}
return (
<BlockListBlock
{...props}
className={classnames(className, 'divider divider-' + colorObject.slug)}
/>
);
};
}, 'addDividerClass');
//add filters
addFilter(
'blocks.registerBlockType',
'ursa6/custom-attributes',
addAttributes
);
addFilter(
'editor.BlockEdit',
'ursa6/custom-advanced-control',
withAdvancedControls
);
addFilter(
'blocks.getSaveContent.extraProps',
'ursa6/applyExtraClass',
applyExtraClass
);
addFilter(
'editor.BlockListBlock',
'ursa6/addDividerClass',
addDividerClass
);
What I’ve tried:
Updated code above. I have this working a little better. The classes are applied during edit in the block editor, and on save when saved. The classes are not removed when colors are deselected, and the custom color class is not replaced when changing colors.
Can someone tell me where I went wrong?