After registering a new block in Gutenberg editor, it works fine until save /publish post, the output is fine in front end too, but after refreshing the edit screen, block shows the block validation error:
Content generated by `save` function:
Content retrieved from post body:
<div class="wp-block-gutenberg-examples-post-block3 slider-item"><img src="http://127.0.0.1/wordpress_test/wp-content/uploads/2021/11/41QuqNH75-L.SY344_BO1204203200.jpg" dataid="146"/><img src="http://127.0.0.1/wordpress_test/wp-content/uploads/2021/11/41CoI-EUQML.SX258_BO1204203200.jpg" dataid="149"/></div>
Block validation: Block validation failed for `gutenberg-examples/post-block3`
This is how I register the new block:
blocks.registerBlockType( 'gutenberg-examples/post-block3', {
title: 'post: Controls',
icon: 'universal-access-alt',
category: 'common',
attributes: {
imgUrl: {
type: 'array',
source: 'query',
selector: '.slider-item',
default: [],
query:{
mediaID: {
type: 'number',
source: 'attribute',
attribute: 'data-id',
selector: 'img',
},
mediaURL: {
type: 'string',
source: 'attribute',
attribute: 'src',
selector: 'img',
},
}
},
},
edit: function( props ) {
function selectImage(value) {
props.setAttributes({
imgUrl: value.map(function(val){return{mediaURL:val.url,mediaID:parseInt( val.id, 10 )}}),
});
}
return el( Fragment, {className: props.className},
el( InspectorControls, {},
el( PanelBody, { title: 'Form Settings', initialOpen: true },
el(MediaUpload,
{//onSelectImages
onSelect: selectImage,
multiple: true,
allowedTypes: 'image',
gallery:true,
value:props.attributes.imgUrl.map(function(val){
return val.mediaID;
}),
render(renderProps) {
return el('button',
{
onClick: renderProps.open,
},
'upload image',
)
}
},
null
),
),),
);
},
save: function( props ) {
return el('div',{className: 'slider-item'},props.attributes.imgUrl.map(function(data){
return el('img',
{
src: data.mediaURL,
'data-id':data.mediaID,
},
null
);
}),
);
},
} );
After registering a new block in Gutenberg editor, it works fine until save /publish post, the output is fine in front end too, but after refreshing the edit screen, block shows the block validation error:
Content generated by `save` function:
Content retrieved from post body:
<div class="wp-block-gutenberg-examples-post-block3 slider-item"><img src="http://127.0.0.1/wordpress_test/wp-content/uploads/2021/11/41QuqNH75-L.SY344_BO1204203200.jpg" dataid="146"/><img src="http://127.0.0.1/wordpress_test/wp-content/uploads/2021/11/41CoI-EUQML.SX258_BO1204203200.jpg" dataid="149"/></div>
Block validation: Block validation failed for `gutenberg-examples/post-block3`
This is how I register the new block:
blocks.registerBlockType( 'gutenberg-examples/post-block3', {
title: 'post: Controls',
icon: 'universal-access-alt',
category: 'common',
attributes: {
imgUrl: {
type: 'array',
source: 'query',
selector: '.slider-item',
default: [],
query:{
mediaID: {
type: 'number',
source: 'attribute',
attribute: 'data-id',
selector: 'img',
},
mediaURL: {
type: 'string',
source: 'attribute',
attribute: 'src',
selector: 'img',
},
}
},
},
edit: function( props ) {
function selectImage(value) {
props.setAttributes({
imgUrl: value.map(function(val){return{mediaURL:val.url,mediaID:parseInt( val.id, 10 )}}),
});
}
return el( Fragment, {className: props.className},
el( InspectorControls, {},
el( PanelBody, { title: 'Form Settings', initialOpen: true },
el(MediaUpload,
{//onSelectImages
onSelect: selectImage,
multiple: true,
allowedTypes: 'image',
gallery:true,
value:props.attributes.imgUrl.map(function(val){
return val.mediaID;
}),
render(renderProps) {
return el('button',
{
onClick: renderProps.open,
},
'upload image',
)
}
},
null
),
),),
);
},
save: function( props ) {
return el('div',{className: 'slider-item'},props.attributes.imgUrl.map(function(data){
return el('img',
{
src: data.mediaURL,
'data-id':data.mediaID,
},
null
);
}),
);
},
} );
Share
Improve this question
asked Jan 4, 2022 at 21:14
MortezaMorteza
1521 gold badge1 silver badge10 bronze badges
1 Answer
Reset to default 1The block validation failed because the editor did not parse the attributes from all images (in the saved post content), and it's because your save
function is returning only one .slider-item
div containing multiple img
tags, like so:
<div class="slider-item">
<img src="..." data-id="123" />
<img src="..." data-id="456" />
...
</div>
And what should actually be returned is one or more .slider-item
divs, each containing just one img
tag, like so:
<div class="slider-item">
<img src="..." data-id="123" />
</div>
<div class="slider-item">
<img src="..." data-id="456" />
</div>
...
So make sure that your save
function returns the correct markup based on your block attribute's definition. E.g.
save: function( props ) {
return el(
'div',
useBlockProps.save( {
className: 'slider-items', // note the "itemS"
} ),
props.attributes.imgUrl.map( function ( data, i ) {
return el(
'div',
{
className: 'slider-item',
key: 'slider-item-' + i,
},
el( 'img', {
src: data.mediaURL,
'data-id': data.mediaID,
}, null )
); // end of .slider-item
} ),
); // end of .slider-items
},
Additional Notes
useBlockProps()
should be used in theedit
function, anduseBlockProps.save()
in thesave
function.When returning an array of elements, each of them should have a unique
key
.
So in the above example, I used useBlockProps.save()
and key
.
References
https://developer.wordpress/block-editor/reference-guides/block-api/block-attributes/#query
https://developer.wordpress/block-editor/reference-guides/block-api/block-edit-save/
https://reactjs/docs/lists-and-keys.html#keys