Gutenberg block don't save rich text content
-
26-04-2021 - |
Вопрос
I could not get to work. When published the content the attribute innerContent didn't save. Here is what I tried.
block.js
// Import CSS.
import './style.scss';
import './editor.scss';
const { __ } = wp.i18n;
const { registerBlockType } = wp.blocks;
const { RichText } = wp.editor;
registerBlockType( 'hall/block-server-side-render', {
title: __( 'Server Side Rendering' ),
icon: 'shield',
category: 'common',
keywords: [
__( 'Server Side Rendering' )
],
attributes: {
innerContent: {
type: 'array',
source: 'children',
selector: 'p'
}
},
edit: function( props ) {
function onChangeContent( content ) {
props.setAttributes( { innerContent: content } );
}
return (
<div className={ props.className }>
<div class="gray-bg">
<RichText tagName="p" role="textbox" aria-multiline="true" value={props.attributes.innerContent} onChange={onChangeContent} />
</div>
</div>
);
},
save: function( props ) {
return null;
},
} );
init.php
register_block_type( 'hall/block-server-side-render', array(
'render_callback' => 'hall_render_inner_content',
'attributes' => array(
'innerContent' => array(
'type' => 'array'
)
)
));
function hall_render_inner_content( $attributes ) {
$innerContent = $attributes['innerContent'];
return '<div class="inner-content">' . $innerContent . '</div>';
}
Решение
Short Answer: When saving an attribute, always respect the attribute type. So if your attribute is of the array
type, then save the value as an array, e.g. props.setAttributes( { innerContent: [ content ] } )
.
Longer Answer
Your
register_block_type()
call is missing theeditor_script
parameter. See the block editor handbook for details, but basically, you would need something like:function hall_register_block() { wp_register_script( 'hall-block-server-side-render', '/path/to/block.js', array( 'wp-i18n', 'wp-blocks', 'wp-block-editor' ), '1.0' ); register_block_type( 'hall/block-server-side-render', array( 'render_callback' => 'hall_render_inner_content', 'attributes' => array( 'innerContent' => array( 'type' => 'array', // You should set a default value: 'default' => array(), // if the attribute is an array // 'default' => '', // if the attribute is a string ), ), // Here, your code is missing the block's script: 'editor_script' => 'hall-block-server-side-render', ) ); } add_action( 'init', 'hall_register_block' );
You defined the
innerContent
attribute as an array, so you would need to save it (via theprops.setAttributes()
) as an array:function onChangeContent( content ) { // Save the value as an array. props.setAttributes( { innerContent: [ content ] } ); }
And omit the attribute's
source
andselector
properties so that the attributes would be saved to (and read from) the block's comment delimiter.attributes: { innerContent: { type: 'array', // No need for these two: // source: 'children', // selector: 'p' } },
But then, in your block render callback (
hall_render_inner_content()
), you would also need to parse the HTML in the attribute value (which is not a simple array such as[ 'HTML here', 'another HTML here', 'etc etc' ]
), and note that, in that callback, the$content
is (or would supposedly be) an array and not a string.So you should probably just change the attribute type to
string
, i.e. just change the abovetype: 'array',
totype: 'string',
. And that way, you wouldn't need to save the attribute as an array.You should import
RichText
fromwp.blockEditor
and notwp.editor
:const { RichText } = wp.blockEditor; // use this const { RichText } = wp.editor; // not this
Другие советы
You should be using string as attribute type, as in previous answer, and possibly set multiline attribute to true on Richtext and use multiline parameter in attributes, as explained here. https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#html
If you will be using multiline, be sure to set 'div.gray-bg' as selector in your case.