In my block, I have set up a toggle control to add or remove a class and change the layout of the block in both the editor and the front end of the site.
Instances where it works:
Instances where it doesn't work:
While it works perfectly fine initially, it seems that once the block is saved, there is no way to re-toggle or change the layout again. I'm working with three main files: edit.js, index.js, and save.js. Please refer to the code provided below.
edit.js
import { __ } from '@wordpress/i18n';
import {
RichText,
InspectorControls,
MediaUpload,
useBlockProps,
InnerBlocks,
} from '@wordpress/block-editor';
import { PanelBody, Button, ToggleControl } from '@wordpress/components';
const ALLOWED_BLOCKS = ['core/button'];
import './editor.scss';
const Edit = ({ attributes, setAttributes }) => {
const { toggleOn, customClass, align } = attributes;
const onToggleChange = (newValue) => {
setAttributes({ toggleOn: newValue });
};
const onSelectBlockBackground = (newBlockBackground) => {
setAttributes({
blockBackground: newBlockBackground.sizes.full.url,
});
};
const blockProps = useBlockProps({
className: `wp-block-create-block-callout-block ${customClass} ${toggleOn ? 'toggle-on-horizontal-cta' : ''}`,
'data-align': align,
});
return (
<div {...blockProps}>
<InspectorControls>
<PanelBody title={__('Toggle on horizontal or vertical layout')}>
<ToggleControl
label={__('Toggle On')}
checked={toggleOn}
onChange={onToggleChange}
/>
</PanelBody>
<PanelBody title={__('Select Background Image')}>
<p>
<strong>{__('Select a Background Image:')}</strong>
</p>
<MediaUpload
onSelect={onSelectBlockBackground}
type="image"
value={attributes.blockBackground.url}
render={({ open }) => (
<Button
className="editor-media-placeholder__button is-button is-default is-large"
icon="upload"
onClick={open}
>
{__('Select Image')}
</Button>
)}
/>
</PanelBody>
</InspectorControls>
<div
className={`callout-cta`}
style={{
backgroundImage: attributes.blockBackground !== '' ? `url("${attributes.blockBackground}")` : 'none',
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
}}
>
<RichText
tagName="h2"
value={attributes.mainHeading}
onChange={(mainHeading) => setAttributes({ mainHeading })}
placeholder={__('Main Heading')}
className="main-heading"
/>
<RichText
tagName="p"
value={attributes.mainContent}
onChange={(mainContent) => setAttributes({ mainContent })}
placeholder={__('Main Content')}
className="main-content"
/>
<InnerBlocks allowedBlocks={ALLOWED_BLOCKS} />
</div>
</div>
);
};
export default Edit;
index.js
import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import { RichText, InspectorControls, MediaUpload, useBlockProps } from '@wordpress/block-editor';
import { PanelBody, Button } from '@wordpress/components';
import './style.scss';
import Edit from './edit';
import save from './save';
const validAlignments = ['full'];
registerBlockType('create-block/callout-block', {
title: __('Callout Block', 'callout-block'),
supports: {
html: false,
align: true,
},
attributes: {
mainHeading: {
type: 'string',
source: 'html',
selector: '.main-heading',
},
mainContent: {
type: 'string',
source: 'html',
selector: '.main-content',
},
blockBackground: {
type: 'string',
default: '',
},
align: {
type: 'string',
default: 'full',
},
toggleOn: {
type: 'boolean',
default: false,
source: 'attribute',
attribute: 'data-toggle-on', // Use the attribute name that corresponds to the class you're toggling
},
},
getEditWrapperProps( attributes ) {
const { align } = attributes;
if (-1 !== validAlignments.indexOf( align ) ) {
return { 'data-align': align };
}
},
edit: Edit,
save,
});
save.js
import { __ } from '@wordpress/i18n';
import {
RichText,
InspectorControls,
MediaUpload,
useBlockProps,
InnerBlocks,
} from '@wordpress/block-editor';
import { PanelBody, Button } from '@wordpress/components';
export default function save({ className, attributes }) {
const { toggleOn } = attributes;
const blockProps = useBlockProps.save({
'data-align': attributes.align, // Add the data-align attribute with the align value
className: `wp-block-create-block-callout-block ${className} ${toggleOn ? 'toggle-on-horizontal-cta' : ''}`,
});
return (
<div className={`wp-block-create-block-callout-block ${className} ${toggleOn ? 'toggle-on-horizontal-cta' : ''}`} {...blockProps}>
<div
className="callout-cta"
style={{
backgroundImage: attributes.blockBackground !== '' ? `url("${attributes.blockBackground}")` : 'none',
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
}}
>
<RichText.Content
tagName="h2"
value={attributes.mainHeading}
className="main-heading"
/>
<RichText.Content
tagName="p"
value={attributes.mainContent}
className="main-content"
/>
<InnerBlocks.Content {...blockProps} />
</div>
</div>
);
}
Looking at your other question in relation to this question/code, I suggest using Block Styles would be a better fit for your scenario.
The need for toggle and related getEditWrapperProps()
is removed entirely with Block Styles, with the advantage that the User can visually preview the style to be applied. Block Styles also enables the option to register additional styles in the future without needing to change the underlying block properties. It may also be useful for your custom background properties.
Remove the toggle and related code/attributes.
Register a block style for "horizontal" for your block (as the default layout is "stacked/vertical").
index.js
wp.blocks.registerBlockStyle('create-block/callout-block', [
{
name: 'horizontal',
label: 'Horizontal',
}
]);
style.scss
.wp-block-create-block-callout-block {
padding:0.25em;
border: 2px solid orange;
display:flex !important;
flex-direction: column; /* default is stacked */
&.is-style-horizontal{
flex-direction: row;
border-color: purple;
}
}
registerBlockType()
:index.js
registerBlockType('create-block/callout-block', {
...
example: {
attributes: {
mainHeading: "Hello World",
mainContent: "Lorem Ipsum"
}
}
...
});