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>
);
}
});
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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:
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
-
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 } /> -
If you look at the above screenshot, the block’s outmost wrapper has two
classattributes, which results in the “Expected attributeclassof value `…” notice:<div class="col-md-5 offset-md-1" class="wp-block-myblog-check-list">To fix that, use the
classNameattribute and notclassin your<div>:And although
classdoes work (despite being a reserved keyword in JavaScript), the (current) React documentation actually says, “To specify a CSS class, use theclassNameattribute.“, 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> ); -
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’seditandsavecallbacks. 🙂Example in your
savecallback:const blockProps = useBlockProps.save( { className: 'col-md-5 offset-md-1' } ); return ( <div { ...blockProps }> <div className="green-check-list-container"> ... your code. </div> </div> );
Method 2
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.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0
