2

I created a Gutenberg block but after saving it and going back into the post I receive this error:

This block contains unexpected or invalid content

I couldn't find any inconsistencies and I had a friend also take a look over to see if there was anything amiss. What am I doing wrong?

registerBlockType('myblog/check-list', {
    //Built-in Attributes
    title: 'Check List',
    description: 'Generate a bulleted list with green checkmarks',
    icon: 'list-view',
    category: 'design',

    //Custom Attributes
    attributes: {
        title: {
            type: 'string',
            source: 'html',
            selector: 'h2'
        },
        text: {
            type: 'string',
            source: 'html',
            selector: 'p'
        },
        titleColor: {
            type: 'string',
            default: '#383838'
        },
        checkListItemOne: {
            type: 'string',
            source: 'html',
            selector: 'span'
        },
        checkListItemTwo: {
            type: 'string',
            source: 'html',
            selector: 'span'
        }
    },

    //Built-in Functions
    edit({attributes, setAttributes}) {
        const{
            title,
            text,
            titleColor,
            checkListItemOne,
            checkListItemTwo,
        } = attributes;

        //Custom Functions
        
        function onChangeTitle(newTitle) {
            setAttributes( { title: newTitle } );
        }

        function onChangeText(newText) {
            setAttributes( { text: newText } );
        }

        function onTitleColorChange(newColor){
            setAttributes( { titleColor: newColor } );
        }

        function onChangeCheckListItemOne(newListItemOne) {
            setAttributes( { checkListItemOne: newListItemOne})
        }

        function onChangeCheckListItemTwo(newListItemTwo) {
            setAttributes( { checkListItemTwo: newListItemTwo})
        }
        

        return ([
            <InspectorControls style={ { marginBottom: '40px' } }>
                <PanelBody title={ 'Headline Color' }>
                    <p><strong>Choose Title Color</strong></p>
                    <ColorPalette 
                        value={titleColor} 
                        onChange={onTitleColorChange} 
                    />
                </PanelBody>
            </InspectorControls>,

            <div class="col-md-5 offset-md-1">
                <div class="green-check-list-container">
                    <RichText 
                        key="editable"
                        tagName="h2"
                        placeholder="Headline for check list" 
                        value= { title }
                        onChange= { onChangeTitle }
                        style= { { color: titleColor } }
                    />
                    <RichText 
                        key="editable"
                        tagName="p"
                        placeholder="Additional context for the list" 
                        value= { text }
                        onChange= { onChangeText }
                    />
                    <ul class="green-check-list-items">
                        <li>
                            <RichText 
                                key="editable"
                                tagName="span"
                                placeholder="List Item" 
                                value= { checkListItemOne }
                                onChange= { onChangeCheckListItemOne }
                            />
                        </li>                        
                        <li>
                            <RichText 
                                key="editable"
                                tagName="span"
                                placeholder="List Item" 
                                value= { checkListItemTwo }
                                onChange= { onChangeCheckListItemTwo }
                            />
                        </li>
                    </ul>
                </div>
            </div>
        ]);
    },

    save({ attributes }) {
        const {
            title,
            text,
            titleColor,
            checkListItemOne,
            checkListItemTwo,
        } = attributes;

        return (
            <div class="col-md-5 offset-md-1">
                <div class="green-check-list-container">
                    <h2 style={ { color: titleColor } }>{title}</h2>
                    <p>{ text }</p>
                    <ul class="green-check-list-items">
                        <li>
                            <span>{ checkListItemOne }</span>
                        </li>
                        <li>
                            <span>{ checkListItemTwo }</span>
                        </li>
                    </ul>
                </div>
            </div>
        );
    }
});
0

2 Answers 2

5
+50

The main issue in your code is with these two attributes which use the exact same selector (the first span element in your block content):

checkListItemOne: {
    type: 'string',
    source: 'html',
    selector: 'span' // same as below
},
checkListItemTwo: {
    type: 'string',
    source: 'html',
    selector: 'span' // same as above
}

Which means the block editor will always use the content of the first span element in the saved block content, which then results in a "block validation failed" error like so:

enter image description here

Therefore, make sure that you set the proper selector value for your block attributes. Here's an example using the CSS selectors element > element and :nth-child(n):

checkListItemOne: {
    type: 'string',
    source: 'html',
    selector: 'li:nth-child(1) > span'
},
checkListItemTwo: {
    type: 'string',
    source: 'html',
    selector: 'li:nth-child(2) > span'
}

Additional Issues/Notes

  1. The block editor handbook says:

    HTML Formatting Tags Display in the Content

    If the HTML tags from text formatting such as <strong> or <em> are being escaped and displayed on the frontend of the site, this is likely due to an issue in your save function. Make sure your code looks something like <RichText.Content tagName="h2" value={ heading } /> (ESNext) within your save function instead of simply outputting the value with <h2>{ heading }</h2>.

    So for example in your case, you'd use this instead of <span>{ checkListItemOne }</span>:

    <RichText.Content tagName="span" value={ checkListItemOne } />
    
  2. If you look at the above screenshot, the block's outmost wrapper has two class attributes, which results in the "Expected attribute class of value `..." notice:

    <div class="col-md-5 offset-md-1" class="wp-block-myblog-check-list">
    

    To fix that, use the className attribute and not class in your <div>:

    And although class does work (despite being a reserved keyword in JavaScript), the (current) React documentation actually says, "To specify a CSS class, use the className attribute.", so you should use that attribute in all your <div> and other elements having a CSS class.

    return (
        <div className="col-md-5 offset-md-1">
            <div className="green-check-list-container">
                ... your code.
            </div>
        </div>
    );
    
  3. WordPress 5.6.0 uses block editor API version 2 which introduced a new hook named useBlockProps, so I suggest you to use it in your block's edit and save callbacks. :)

    Example in your save callback:

    const blockProps = useBlockProps.save( { className: 'col-md-5 offset-md-1' } );
    
    return (
        <div { ...blockProps }>
            <div className="green-check-list-container">
                ... your code.
            </div>
        </div>
    );
    
1
  • 2
    I've updated your examples to use className instead of class (as this is the correct way per React doc). If this is unwanted, please rollback my edit, Sally.
    – kero
    Commented Jan 11, 2021 at 17:11
1

You can check the WordPress Core file source and try to understand why this error appears, just search for the error message here:

https://raw.githubusercontent.com/WordPress/WordPress/master/wp-includes/js/dist/block-editor.js

From my point of view, there is might be a problem with using custom HTML elements. Try to replace all custom HTML with casual <div> and see what will happen. If that error is gone, then the source is these elements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.