Describe the bug
I created a block that gets the values of some custom meta fields and adds them to block attributes. However, when I try to save the new value of a field it seems that the editor saves the value but when I refresh the page the block displays the old value. It actually didn't save the new value to meta field.
I added support for 'custom-fields' and I use the following code for the block:
el( InspectorControls, {},
el( TextControl, {
label: 'Meta Field',
value: props.attributes.meta_field,
onChange: ( value ) => { props.setAttributes( { meta_field: value } ); },
} )
)
Also, i have one more field that doesn't get the value from a meta field and it seems to work great as it saves the new value (not to a meta field).
Does anyone have a solution for this? Thanks in advance!
Also I can't display the value on the frontend. I can see it on backend but on the frontend it is empty. Any ideas?
You need to use register_post_meta() to make your meta data available in the REST API so that the values can be updated by the editor.
@swissspidy
I have already added register_post_meta() but it doesn't work. I don't even get the values on the frontend.
The meta data is available in the REST API but it is not updated.
Would you mind sharing your whole block registration code here then so we can verify this?
Sure. Here it is:
index.php file:
function basic_info_block_init() {
wp_enqueue_script(
'basic-info-block',
plugins_url( 'basic-info-block.js', __FILE__ ),
array( 'wp-blocks', 'wp-element', 'wp-components', 'wp-editor' )
);
register_block_type( 'myblock/basic-info-block', array(
'attributes' => array(
'style' => array(
'type' => 'string',
),
'event_short_info' => array(
'type' => 'string',
'source' => 'meta',
'meta' => 'event_short_info',
),
'event_start_date' => array(
'type' => 'string',
'source' => 'meta',
'meta' => 'event_start_date',
),
'event_end_date' => array(
'type' => 'string',
'source' => 'meta',
'meta' => 'event_end_date',
),
'event_free_entrance' => array(
'type' => 'string',
'source' => 'meta',
'meta' => 'event_free_entrance',
),
),
'editor_script' => 'basic-info-block',
'render_callback' => 'basic_info_block',
) );
}
add_action( 'init', 'basic_info_block_init' );
and basic-info-block.js:
var el = wp.element.createElement,
registerBlockType = wp.blocks.registerBlockType,
ServerSideRender = wp.components.ServerSideRender,
TextControl = wp.components.TextControl,
SelectControl = wp.components.SelectControl,
InspectorControls = wp.editor.InspectorControls;
registerBlockType( 'myblock/basic-info-block', {
title: 'JTEC - Basic Info',
icon: 'megaphone',
category: 'widgets',
edit: function( props ) {
return [
el( ServerSideRender, {
block: 'myblock/basic-info-block',
attributes: props.attributes,
} ),
el( InspectorControls, {},
el( SelectControl, {
label: 'Style',
value: props.attributes.style,
options: [
{ value: 'style-1', label: 'Style 1' },
{ value: 'style-2', label: 'Style 2' },
],
onChange: ( value ) => { props.setAttributes( { style: value } ); },
} ),
el( TextControl, {
label: 'Short Info',
value: props.attributes.event_short_info,
onChange: ( value ) => { props.setAttributes( { event_short_info: value } ); },
} ),
el( TextControl, {
label: 'Start Date',
value: props.attributes.event_start_date,
onChange: ( value ) => { props.setAttributes( { event_start_date: value } ); },
} ),
el( TextControl, {
label: 'End Date',
value: props.attributes.event_end_date,
onChange: ( value ) => { props.setAttributes( { event_end_date: value } ); },
} ),
el( SelectControl, {
label: 'Free Entrance',
value: props.attributes.event_free_entrance,
options: [
{ value: 'no', label: 'No' },
{ value: 'yes', label: 'Yes' },
],
onChange: ( value ) => { props.setAttributes( { event_free_entrance: value } ); },
} ),
),
];
},
save: function( ) {
return null;
},
} );
Thanks in advance.
@swissspidy
Do you need something else? I also have this callback function to return the value:
function basic_info_block( $atts ) {
return $atts['event_short_info'];
}
I think I found the problem here.
I had to remove the save_post action from the old code as it replaced the new value with old one. However, it seems that I still can't display the value in the frontend. The callback function works great in the backend but on the frontend it is empty.
For example, if I add:
function basic_info_block( $atts ) {
$short_info = 'Short Info: ' . $atts['event_short_info']
return $short_info;
}
then I only get Short Info: in the frontend and the $atts['event_short_info'] is empty.
That is to be expected. When you store attributes in post meta, they're not part of $atts.
You have to retrieve them using get_post_meta() instead.
@izachros I am having the same problem as you. How did you fix it in the end? Unfortunately, I have no clue which function you mean with "save_post"?
I had to remove the save_post action from the old code as it replaced the new value with old one.
I am also able to save my meta value when creating a new post (custom post type), however, the update fails and sets the initial value/changes nothing.
el( TextControl, {
label: 'Webseite',
value: props.attributes.website,
onChange: function( website ) {
setAttributes({ website });
}
} ),
Some other people seem to have the same problem and its a reported bug:
@bracketsberlin I recommend you to create a new issue with your request instead of commenting on old, closed issues. Otherwise nobody will really notice your question.
Also, you need to share all your block's code (including how you configured attributes), otherwise it's impossible to know what is going wrong.
Please also note that you'll need to use register_post_meta() to properly make the meta data accessible via the REST API. Otherwise Gutenberg is not able to read/write to it.
Unfortunately, I have no clue which function you mean with "save_post"?
save_post is an action hook in WordPress, not a function. For your use case, that hook is irrelevant though.
@bracketsberlin
First, you have to register your custom meta fields using a function like this:
function my_plugin_register_post_metas_init() {
register_post_meta( 'my_cpt', 'meta_field', array(
'show_in_rest' => true,
'single' => true,
'type' => 'string',
) );
}
add_action( 'init', 'my_plugin_register_post_metas_init' );
Then, you have to change your code to:
el( SelectControl, {
label: 'Website',
value: props.attributes.website,
onChange: ( value ) => { props.setAttributes( { website: value } ); },
} ),
Also, make sure that you use add_meta_boxes action as this:
function my_plugin_meta() {
add_meta_box( 'my_plugin_meta_box',
'Metabox Label',
'display_my_plugin_meta_box',
'my_cpt', 'normal', 'high',
array(
'__block_editor_compatible_meta_box' => true,
'__back_compat_meta_box' => true,
)
);
}
add_action( 'add_meta_boxes', 'my_plugin_meta' );
Hope this will help you fix the problem.
@izachros Thank you very much for your help. The add_meta_box() function seems to add meta boxes for custom post types that do not use Gutenberg blocks? I'd like to use Gutenberg blocks. I created a new issue here: https://github.com/WordPress/gutenberg/issues/16023
Or do I get something wrong and you also propose your solution when it comes to working with Gutenberg blocks? As @swissspidy suggested, it probably makes more sense to work on the new issue.
Thanks for your help, guys.
Yeah that add_meta_box part is unnecessary for this.