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

Block validation failed #14433

Closed
joshrouwhorst opened this issue Mar 14, 2019 · 1 comment
Closed

Block validation failed #14433

joshrouwhorst opened this issue Mar 14, 2019 · 1 comment
Labels
[Type] Help Request Help with setup, implementation, or "How do I?" questions.

Comments

@joshrouwhorst
Copy link

I have a block that basically functions as a background. So it creates a div that gets set with some options for background color and padding, and within it there is InnerBlocks.

Now, I'm trying to update this block with a new div to wrap the InnerBlocks that will have an optional container class.

Here's the error I'm getting in the editor when I load a page with the previous version of the block:

Block validation: Block validation failed for `kcdp/layout`

Expected:

<div class="wp-block-kcdp-layout alignfull kcdp-layout white-background medium-padding no-side-padding" data-side-padding="no-side-padding" data-background="white-background" data-padding="medium-padding" data-container="false"><div class=""></div></div>

Actual:

<div class="wp-block-kcdp-layout alignfull kcdp-layout white-background medium-padding no-side-padding" data-side-padding="no-side-padding" data-background="white-background" data-padding="medium-padding"></div>

As I understand it, the save function in the deprecated object is how Wordpress figures out that the block should be migrated. What's odd to me is that the "Actual" in this error is exactly what should be getting output by the deprecated save function. But it seems like it's not matching on that save function's output.

Here's the code I'm using:

const { __ } = wp.i18n;
const { InspectorControls, InnerBlocks, MediaUpload, PlainText } = wp.editor;
const { registerBlockType } = wp.blocks;
const { SelectControl, PanelBody, CheckboxControl } = wp.components;

// Import our CSS files
import './style.scss';
import './editor.scss';

const el = wp.element.createElement

registerBlockType('kcdp/layout', {   
    title: 'KCDP - Layout',
    icon: 'nametag',
    description: 'Creates a background and lets you set padding around your content.',
    category: 'layout',
    supports: {
        align: ['full', 'center']
    },
    attributes: {
        background: {
            attribute: 'data-background',
            selector: '.kcdp-layout',
            default: ''
        },
        padding: {
            attribute: 'data-padding',
            selector: '.kcdp-layout',
            default: ''
        },
        sidePadding: {
            attribute: 'data-side-padding',
            selector: '.kcdp-layout',
            default: 'no-side-padding'
        },
        backgroundImage: {
            attribute: 'data-background-image',
            selector: '.kcdp-layout',
            default: null
        },
        height: {
            attribute: 'data-height',
            selector: '.kcdp-layout',
            default: null
        },
        container: {
            attribute: 'data-container',
            selector: '.kcdp-layout',
            default: false
        }
    },
    edit({ attributes, setAttributes, className }) {
        if (!attributes.align) setAttributes({ align: 'full' });
        var classes = `kcdp-layout ${attributes.background} ${attributes.padding}`;

        if (attributes.container) {
            classes += ' container';
        }

        var style = {};

        if (attributes.backgroundImage) {
            style.backgroundImage = 'url(' + attributes.backgroundImage + ')';
        }

        if (attributes.height) {
            style.height = attributes.height;
        }
        
        return (
            <div className={className}>
                <div className={classes} style={style}>
                    <InspectorControls>
                        <PanelBody title={ __( 'Background' ) }>
                            <SelectControl
                                label="Background"
                                value={ attributes.background }
                                options={ [
                                    { label: 'White', value: 'white-background' },
                                    { label: 'Dark Blue', value: 'dark-blue-background' },
                                    { label: 'Blue', value: 'blue-background' },
                                    { label: 'Gray', value: 'gray-background' },
                                    { label: 'Transparent', value: '' }
                                ] }
                                onChange={ ( val ) => { setAttributes( { background: val } ) } }
                            />
                        </PanelBody>
                        <PanelBody title={ __( 'Background Image' ) }>
                            <MediaUpload
                                onSelect={(media) => setAttributes({backgroundImage: media.url})}
                                type="image"
                                value={ attributes.imageID }
                                render={({ open }) => {
                                    var removeImage = () => {
                                        setAttributes({backgroundImage: null})
                                    };

                                    if (attributes.backgroundImage) {
                                        return (
                                            <button onClick={removeImage}>
                                                Remove Image
                                            </button>
                                        );
                                    }
                                    else {
                                        return (
                                            <button onClick={open}>
                                                Select Image
                                            </button>
                                        );
                                    }
                                }}
                            />
                        </PanelBody>
                        <PanelBody title={ __( 'Container' ) }>
                            <label>
                                Wrap in container?
                                <CheckboxControl
                                    onChange={ isChecked => setAttributes({ container: isChecked }) }
                                    checked={ attributes.container }
                                />
                            </label>
                        </PanelBody>
                        <PanelBody title={ __( 'Padding' ) }>
                            <SelectControl
                                label="Padding"
                                value={ attributes.padding }
                                options={ [
                                    { label: 'None', value: '' },
                                    { label: 'Tiny', value: 'tiny-padding' },
                                    { label: 'Small', value: 'small-padding' },
                                    { label: 'Medium', value: 'medium-padding' },
                                    { label: 'Large', value: 'large-padding' }
                                ] }
                                onChange={ ( val ) => { setAttributes( { padding: val } ) } }
                            />
                        </PanelBody>
                        <PanelBody title={ __( 'Side Padding' ) }>
                            <SelectControl
                                label="Side Padding"
                                value={ attributes.sidePadding }
                                options={ [
                                    { label: 'None', value: 'no-side-padding' },
                                    { label: 'Small', value: 'small-side-padding' },
                                    { label: 'Medium', value: 'medium-side-padding' },
                                    { label: 'Large', value: 'large-side-padding' }
                                ] }
                                onChange={ ( val ) => { setAttributes( { sidePadding: val } ) } }
                            />
                        </PanelBody>
                        <PanelBody>
                            <label>Height
                                <PlainText
                                        onChange={ content => setAttributes({ height: content }) }
                                        value={ attributes.height }
                                        placeholder="Height"
                                        className=""
                                    />
                            </label>
                            <div className="instructions">
                                Be sure to specify pixels or percentage (ie, '100px' or '100%')
                            </div>
                        </PanelBody>
                    </InspectorControls>
                    <div className="edit">
                        <InnerBlocks />
                    </div>
                </div>
            </div>
        );
    },

    save({ attributes, className }) {
        var classes = [ 'kcdp-layout', className, attributes.background, attributes.padding, attributes.sidePadding ];
        var style = {};

        var containerClass = '';

        if (attributes.container) {
            containerClass = 'container';
        }

        if (attributes.backgroundImage) {
            style.backgroundImage = 'url(' + attributes.backgroundImage + ')';
        }

        if (attributes.height) {
            style.height = attributes.height;
        }

        return (
            <div className={classes} 
                    data-side-padding={attributes.sidePadding}
                    data-background={attributes.background} 
                    data-padding={attributes.padding}
                    data-background-image={attributes.backgroundImage}
                    data-height={attributes.height}
                    data-container={attributes.container}
                    style={style}>
                <div class={containerClass}>
                    <InnerBlocks.Content />
                </div>
            </div>
        );
    },

    deprecated: [
        {
            attributes: {
                background: {
                    attribute: 'data-background',
                    selector: '.kcdp-layout',
                    default: ''
                },
                padding: {
                    attribute: 'data-padding',
                    selector: '.kcdp-layout',
                    default: ''
                },
                sidePadding: {
                    attribute: 'data-side-padding',
                    selector: '.kcdp-layout',
                    default: 'no-side-padding'
                },
                backgroundImage: {
                    attribute: 'data-background-image',
                    selector: '.kcdp-layout',
                    default: null
                },
                height: {
                    attribute: 'data-height',
                    selector: '.kcdp-layout',
                    default: null
                },
            },
            supports: ['full', 'center'],
            migrate(attributes, innerBlocks) {
                attributes.container = false;
                return [
                    attributes
                ];
            },
            save({attributes, className}) {
                var classes = [ 'kcdp-layout', className, attributes.background, attributes.padding, attributes.sidePadding ];
                var style = {};

                if (attributes.backgroundImage) {
                    style.backgroundImage = 'url(' + attributes.backgroundImage + ')';
                }

                if (attributes.height) {
                    style.height = attributes.height;
                }

                return (
                    <div className={classes} 
                            data-side-padding={attributes.sidePadding}
                            data-background={attributes.background} 
                            data-padding={attributes.padding}
                            data-background-image={attributes.backgroundImage}
                            data-height={attributes.height}
                            style={style}>
                        <InnerBlocks.Content />
                    </div>
                );
            }
        },
    ]
});

Thank you for any help you can provide!

@youknowriad youknowriad added the [Type] Help Request Help with setup, implementation, or "How do I?" questions. label Mar 14, 2019
@joshrouwhorst
Copy link
Author

I actually got this solved. I found this thread which explained the error I was receiving was the correct behavior for the when you have a new block version and load the page with the old block version on it, and it will fix itself after you update the page. I did experience a problem earlier where updating the page was breaking all of these blocks, but that seems to have been cleared up by tinkering with it.

If anyone knows of a good article or thread that explains or gives examples of deprecation, especially the migrate function, I'd love to see it. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Help Request Help with setup, implementation, or "How do I?" questions.
Projects
None yet
Development

No branches or pull requests

2 participants