Gutenberg: Post Meta is not saved for custom post types

Created on 14 Mar 2018  路  9Comments  路  Source: WordPress/gutenberg

Issue Overview


When setting up a basic custom post type, and using a basic custom block that sets an attribute source to meta, the post_meta is not saved for the custom post type. The post meta is saved, however, for the built-in post post type.

Steps to Reproduce (for bugs)


  1. Install Gutenberg
  2. Set up a basic post type as outlined below:
function register_event_post_type() {
    $args = array(
        'public' => true,
        'label'  => 'Events',
        'show_in_rest' => true,
    );
    register_post_type( 'event', $args );
}
add_action( 'init', 'register_event_post_type' );
  1. Set up a basic custom block type as outlined below:
const { __ } = wp.i18n; // Import __() from wp.i18n
const { registerBlockType, RichText } = wp.blocks; // Import registerBlockType() from wp.blocks

registerBlockType( 'cgb/block-event-meta', {
    title: __( 'event-meta-block' ),
    icon: 'shield',
    category: 'common',
    attributes: {
        eventDate: {
            type: 'string',
            source: 'meta',
            meta: 'eventDate',
        },
    },
    edit: function( props ) {
        return (
            <div className={ props.className }>
                <RichText
                    tagName="h2"
                    className={ props.className }
                    value={ props.attributes.eventDate }
                    onChange={ ( eventDate ) => props.setAttributes( { eventDate } ) }
                    focus={ props.focus }
                    setFocus={ props.setFocus }
                    placeholder={ __( 'Event Date' ) }
                />
            </div>
        );
    },

    save: function( props ) {
        return (
            <div className={ props.className }>
                <p>{ props.attributes.eventDate }</p>
            </div>
        );
    },
} );
  1. Add a new "Event" post
  2. Add the "Event Date" block to the new Event post
  3. Save the post


Wordpress: 4.9.4
Gutenberg: 2.4.0

Expected Behavior


A row in the post_meta table corresponding to the event date meta information

Current Behavior


No meta information is saved

Possible Solution


The post meta is saved when the post type is post, this may indicate that a post type is hardcoded to "post" somewhere?

[Type] Bug

Most helpful comment

I think I have found a solution for this now. The problem is that the register_meta() function currently does not support custom post types. This workaround makes all of the registered meta fields available for all post types in the API, so if you don't mind them showing up, it is a ok solution.

The first thing you have to do is make sure that you register the meta for the post type "post" like so:

add_action('init', function () {
    register_meta('post', 'eventDate', [ // Notice we're using "post" as object_type
        'show_in_rest' => true,
        'single' => true
    ]);
});

What you also need to do, is when you register your custom post type, you have to make sure it supports custom fields. Like this:

register_post_type('custom', [
// options...
     'supports' => [
         // ...
         'custom-fields',
     ],
]);

This last steps makes sure that your custom post type exposes the meta-property from the REST API, which is what Gutenberg uses to view/update the data.

Note: If you need to make sure that only your custom post type exposes the meta keys, you should check out this article: https://iandunn.name/2017/03/30/exposing-custom-post-type-meta-for-only-a-single-api-endpoint/ which offers a solution for conditionally render the meta keys.

All 9 comments

Oh, it's also worth mentioning that I did register the meta key so Gutenberg could see it, but the behaviour still doesn't change:

function event_date_meta_init() {
    register_meta( 'event', 'eventDate', array(
        'show_in_rest' => true,
        'single' => true
    ) );
}
add_action( 'init', 'event_date_meta_init' );

I think this problem might come from Wordpress itself, not necessarily Gutenberg. There is some information about how meta fields are handled in the API here https://developer.wordpress.org/rest-api/extending-the-rest-api/modifying-responses/#using-register_rest_field-vs-register_meta. Also there is some examples here https://developer.wordpress.org/reference/functions/register_meta/ which describes registering meta for custom post types, by using "post" as object type, but I have not gotten it to work.

I think I have found a solution for this now. The problem is that the register_meta() function currently does not support custom post types. This workaround makes all of the registered meta fields available for all post types in the API, so if you don't mind them showing up, it is a ok solution.

The first thing you have to do is make sure that you register the meta for the post type "post" like so:

add_action('init', function () {
    register_meta('post', 'eventDate', [ // Notice we're using "post" as object_type
        'show_in_rest' => true,
        'single' => true
    ]);
});

What you also need to do, is when you register your custom post type, you have to make sure it supports custom fields. Like this:

register_post_type('custom', [
// options...
     'supports' => [
         // ...
         'custom-fields',
     ],
]);

This last steps makes sure that your custom post type exposes the meta-property from the REST API, which is what Gutenberg uses to view/update the data.

Note: If you need to make sure that only your custom post type exposes the meta keys, you should check out this article: https://iandunn.name/2017/03/30/exposing-custom-post-type-meta-for-only-a-single-api-endpoint/ which offers a solution for conditionally render the meta keys.

The problem is that RichText produces an array structure and the meta values should be scalar. The #6034 tries to add a format prop to the RichText component to allow HTML to be saved as string into meta attributes.

Alternatively, you can use another component to update your meta value: TextControl, PlainText, DateTimePicker...

>

```
register_post_type('custom', [
// options...
'supports' => [
// ...
'custom-fields',
],
]);

This is unexpected behaviour between register_meta for custom post types. It should be documented. I spend 3 nights to find the reason.

As of WordPress 4.7, you can now set the object_subtype on register_meta to specify a custom post type.

<?php
  register_meta('post', 'field_name', [
    'show_in_rest'   => true,
    'object_subtype' => 'your_custom_post_type_name',
  ]);

?>

Adding 'object_subtype' did not fix this problem, not sure if that was going to fix it.

Hopefully this could help others

<?php

// Don't do this
add_action('init', function () {
    if (is_admin()) {
        register_post_meta($post_type, $name, $definition);
    }
});

// Do this
add_action('init', function () {
    register_post_meta($post_type, $name, $definition);
});

Lost about 4 hours on this!

What you also need to do, is when you register your custom post type, you have to make sure it supports custom fields.

:point_up: Tagging another comment here to highlight this prior comment because it keeps getting linked in discussions: If you're using register_post_meta( 'your_cpt_name', ... and it's not working, make sure your custom post type supports custom-fields. That value must be in the supports array for meta handling to work.

@alexufo I agree it should be documented, there is an open issue on the WP-API/docs repository to add it to the prose documentation but it should also be noted on the register_meta arguments documentation. I'll make a ticket for that.

Edited to update: I have opened a ticket expanding the documentation for show_in_rest.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mhenrylucero picture mhenrylucero  路  3Comments

hedgefield picture hedgefield  路  3Comments

davidsword picture davidsword  路  3Comments

maddisondesigns picture maddisondesigns  路  3Comments

BE-Webdesign picture BE-Webdesign  路  3Comments