Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding custom className in editor.BlockEdit filter, no longer works in 7.7 #20849

Closed
kevinlangleyjr opened this issue Mar 12, 2020 · 8 comments
Closed
Assignees
Labels
[Feature] Extensibility The ability to extend blocks or the editing experience Good First Issue An issue that's suitable for someone looking to contribute for the first time [Package] Block editor /packages/block-editor [Type] Bug An existing feature does not function as intended

Comments

@kevinlangleyjr
Copy link

kevinlangleyjr commented Mar 12, 2020

Describe the bug
When adding custom attributes to a paragraph or heading block, it is no longer possible to also add a className within the editor.BlockEdit filter. Before 7.7, this was possible with the code sample provided below.

/**
 * Filters for the horizontal borders attributes and the classes that get applied.
 *
 */

/**
 * External dependencies
 */
import React from 'react';
import classnames from 'classnames';
import assign from 'lodash.assign';

/**
 * WordPress dependencies
 */
import { PanelBody, RangeControl } from '@wordpress/components';
import { createHigherOrderComponent } from '@wordpress/compose';
import { InspectorControls } from '@wordpress/editor';
import { addFilter, removeFilter } from '@wordpress/hooks';
import { __ } from '@wordpress/i18n';

// Enable max width control on the following blocks.
const enableMaxWidthControlOnBlocks = [
	'core/group',
	'core/heading',
	'core/paragraph',
];

/*
 * Definition of filters to apply. Each requires certain fields.
 *
 * {
 *   @var {string} hook Filter to attach to.
 *   @var {String} namespace Name given to this callback function.
 *   @var {Function} callback Callback function to attach.
 *   @var {Number} priority Priority (defaults to 10).
 * }
 */
const filters = [

	/**
	 * Add block max width attribute to all blocks within enableMaxWidthControlOnBlocks.
	 */
	{
		hook: 'blocks.registerBlockType',
		namespace: 'project/filters/attribute/hasHorizontalBorders',
		callback: ( settings, name ) => {
			// Do nothing if it's not one of our specified blocks.
			if ( ! enableMaxWidthControlOnBlocks.includes( name ) ) {
				return settings;
			}

			// Use Lodash's assign to gracefully handle if attributes are undefined.
			settings.attributes = assign( settings.attributes, {
				maxWidth: {
					type: 'number',
					default: 100,
				},
			} );

			return settings;
		},
	},
	{
		hook: 'editor.BlockEdit',
		namespace: 'project/filters/with-block-max-width-control',
		callback: createHigherOrderComponent( BlockEdit => {
			return props => {
				// Do nothing if it's not one of our specified blocks.
				if ( ! enableMaxWidthControlOnBlocks.includes( props.name ) ) {
					return (
						<BlockEdit { ...props } />
					);
				}

				const {
					attributes,
					setAttributes,
				} = props;

				const {
					className,
					maxWidth,
				} = attributes;

				const blockProps = {
					...props,
					attributes: {
						...attributes,
						className: classnames( className, {
							[ `has-max-width-${maxWidth}` ]: maxWidth !== 100,
						} ),
					},
				};

				return (
					<>
						<BlockEdit { ...blockProps } />
						<InspectorControls>
							<PanelBody title={ __( 'Block Size' ) } icon="leftright">
								<RangeControl
									label={ __( 'Block Max Width' ) }
									value={ maxWidth }
									onChange={ maxWidth => setAttributes( { maxWidth } ) }
									min={ 60 }
									max={ 100 }
									step={ 5 }
								/>
							</PanelBody>
						</InspectorControls>
					</>
				);
			};
		}, 'withBlockMaxWidthControl' ),
	},
	{
		hook: 'blocks.getSaveContent.extraProps',
		namespace: 'project/filters/with-block-max-width-class',
		callback: ( props, blockType, attributes ) => {
			// Do nothing if it's not one of our specified blocks.
			if ( ! enableMaxWidthControlOnBlocks.includes( blockType.name ) ) {
				return props;
			}

			const { maxWidth } = attributes;
			const { className } = props;

			return Object.assign( {}, props, {
				className: classnames( className, {
					[ `has-max-width-${maxWidth}` ]: maxWidth !== 100,
				} ),
			} );
		},
	},
];

filters.forEach( ( { hook, namespace, callback, priority = 10 } ) => {
	addFilter( hook, namespace, callback, priority );
} );

To reproduce
Steps to reproduce the behavior with the above code being enqueued:

  1. Add a paragraph
  2. Set the Max Width
  3. Inspect the paragraph element and notice that the class is not being applied.
  4. If you save the post, the paragraph will save with the correct class but the editor will not display it and therefore it is unable to be styled in the editor.

Expected behavior
Previously to 7.7, I was able to use this same code and add the has-max-width-${maxWidth} className to the BlockEdit element. I tracked the PR down that caused this to change here, https://github.com/WordPress/gutenberg/pull/20658/files#diff-7b64e61cdb441265be8d707b44abad80L158. The same applies to core/column and core/heading blocks.

Desktop (please complete the following information):

  • OS: macOS
  • Browser Chrome
  • Version 80.0
@gziolo gziolo added [Feature] Extensibility The ability to extend blocks or the editing experience [Package] Block editor /packages/block-editor Needs Testing Needs further testing to be confirmed. labels Mar 14, 2020
@noisysocks
Copy link
Member

Looks like we're overwriting className here:

<Component { ...props } context={ context } className={ className } />

Let's add props.className to the classnames() that's on the line above.

@noisysocks noisysocks added Good First Issue An issue that's suitable for someone looking to contribute for the first time [Type] Bug An existing feature does not function as intended and removed Needs Testing Needs further testing to be confirmed. labels Aug 4, 2020
@cguntur
Copy link

cguntur commented Sep 4, 2020

Can I work on this issue?

@noisysocks
Copy link
Member

@cguntur: Go for it! I'll assign you. Feel free to reach out to me on the WordPress Slack if you need any help. My username is noisysocks.

@cguntur
Copy link

cguntur commented Sep 15, 2020

When I use <BlockEdit { ...blockProps } />, with the above code, I can see the max width option in the sidebar, but don't see the actual block in the editor. I tried with another example and when I use (..blockProps), the same thing happens. Am I missing anything?

I added props.className gutenberg/packages/block-editor/src/components/block-edit/edit.js, but I am not able to test if the fix works.

@noisysocks
Copy link
Member

@cguntur: Could you create a PR? That will let me see the code and help 🙂

@cguntur
Copy link

cguntur commented Oct 6, 2020

Here is the PR - #25846. I tried testing this with the code mentioned above, but ,I couldn't get the class names to show up in the editor even after I added props.className in the specific file when I use editor.BlockEdit

The only way the classes show up in the editor is when I use editor.BlockListBlock.

@fabiankaegy
Copy link
Member

Since the API Version 2 with the light block wrapper the class name passed in via props isn't used anymore. Instead the useBlockProps hook is used to generate all the props including the class name.

The way you can already go about adding custom class names to the wrapping block element is by using the `` hook like so:

/**
 * addAdditionalPropertiesInEditor
 */
const addAdditionalPropertiesInEditor = createHigherOrderComponent((BlockList) => {
    return (props) => {
	const { name, attributes, className, } = props;

	// return early from the block modification
	if (! name === 'core/heading' ) {
		return <BlockList {...props} />;
	}

	const additionalClassName = 'hello-world';
	const newClassName = classnames(className, additionalClassName);

	return (
		<BlockList
			{...props}
			className={newClassName}
		/>
	);
    };
}, 'addAdditionalPropertiesInEditor');

addFilter(
    'editor.BlockListBlock',
    'namespace/addAdditionalPropertiesInEditor',
    addAdditionalPropertiesInEditor,
);

Because of this I believe this ticket can be closed out. Please tell me if I'm understanding anything incorrectly in which case we can gladly reopen the issue :)

@realthemes
Copy link

realthemes commented Aug 28, 2024

@fabiankaegy could you please help me understand why I'm unable to filter out two specific classes from my 'core/post-template' block variation? I'm trying to remove the classes is-layout-flow and wp-block-post-template-is-layout-flow, but className appears to be undefined when I attempt to filter them out. Any insights would be greatly appreciated!

Here is my function:

const addStyle = createHigherOrderComponent((BlockList) => {
	return (props) => {
		if (!rltEnableResponsivePostTemplateOnBlocks.includes(props.name)) {
			return <BlockList {...props} />;
		}

		const { attributes, className } = props;

		const {
			respToggle,
			responsiveColumnAttribute,
			responsiveColumnSmAttribute,
			responsiveColumnMdAttribute,
			responsiveColumnLgAttribute,
			responsiveColumnXlAttribute,
			responsiveColumnXxlAttribute,
			columnsGapColumn,
			columnsGapRow,
			columnsGapUnits,
			layout,
		} = attributes;

		// className is undefined
		console.log(className);
		// Filter out unwanted classes
		const filteredClassName = className
			? className
					.split(' ')
					.filter(
						(cls) =>
							cls !== 'is-layout-flow' &&
							cls !== 'wp-block-post-template-is-layout-flow'
					)
					.join(' ')
			: '';

		if (
			respToggle &&
			layout &&
			layout.default &&
			layout.default.type === 'custom' &&
			layout.type !== 'default' &&
			layout.type !== 'grid'
		) {
			const classes = clsx(
				filteredClassName,
				'rlt-has-responsive-columns',
				{
					[`rlt-col-${responsiveColumnAttribute}`]:
						responsiveColumnAttribute,
					[`rlt-col-sm-${responsiveColumnSmAttribute}`]:
						responsiveColumnSmAttribute,
					[`rlt-col-md-${responsiveColumnMdAttribute}`]:
						responsiveColumnMdAttribute,
					[`rlt-col-lg-${responsiveColumnLgAttribute}`]:
						responsiveColumnLgAttribute,
					[`rlt-col-xl-${responsiveColumnXlAttribute}`]:
						responsiveColumnXlAttribute,
					[`rlt-col-xxl-${responsiveColumnXxlAttribute}`]:
						responsiveColumnXxlAttribute,
				}
			);

			const styles = {
				gap: `${columnsGapRow || '24'}${columnsGapUnits || 'px'} ${columnsGapColumn || '24'}${columnsGapUnits || 'px'}`,
			};

			return (
				<BlockList
					{...props}
					className={classes}
					wrapperProps={{ style: styles }}
				/>
			);
		}

		return <BlockList {...props} className={filteredClassName} />;
	};
}, 'addStyle');

wp.hooks.addFilter(
	'editor.BlockListBlock',
	'rlt-responsive-post-template/add-style',
	addStyle
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Extensibility The ability to extend blocks or the editing experience Good First Issue An issue that's suitable for someone looking to contribute for the first time [Package] Block editor /packages/block-editor [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

No branches or pull requests

6 participants