Search code examples
wordpresswordpress-gutenberg

wp.data.select('meta') property undefined with Gutenberg for WordPress


I use Gutenberg with WordPress and I would like to check some fields before the user publish his post.

I would like to check if the featured image, the title and a simple text field in a meta-box are not empty.

If a field is empty a notification is displayed and I locked the "Publish" button.

For the moment all works fine with the featured image and the title. But when I'm trying to check is the text field in the meta-box is empty I got errors :

Uncaught TypeError: Cannot read property '_myprefix_text_metafield' of undefined

I created my meta-box with a text field like that :

import { __ } from '@wordpress/i18n';
import { useSelect, useDispatch } from '@wordpress/data';
import { registerPlugin } from '@wordpress/plugins';
import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
import { TextControl } from '@wordpress/components';

const TextController = (props) => {
    const meta = useSelect(
        (select) =>
        select('core/editor').getEditedPostAttribute('meta')['_myprefix_text_metafield']
    );
    const { editPost } = useDispatch('core/editor');
    return (
        <TextControl
        label={__("Text Meta", "textdomain")}
        value={meta}
        onChange={(value) => editPost({ meta: { _myprefix_text_metafield: value } })}
        />
    );
};

const PluginDocumentSettingPanelDemo = () => (
    <PluginDocumentSettingPanel name="text-presentation" title="Texte de présentation" className="custom-panel custom-panel-presentation" icon=" ">
        <TextController />
    </PluginDocumentSettingPanel>
);

registerPlugin('plugin-document-setting-panel-demo', {
    render: PluginDocumentSettingPanelDemo
});

And to check if all fields are not empty :

const locks = [];

function lock( lockIt, handle, message ) {
    if ( lockIt ) {
        if ( ! locks[ handle ] ) {
            locks[ handle ] = true;
            wp.data.dispatch( 'core/editor' ).lockPostSaving( handle );
            wp.data.dispatch( 'core/notices' ).createNotice(
                'error',
                message,
                { id: handle, isDismissible: false }
            );
        }
    } else if ( locks[ handle ] ) {
        locks[ handle ] = false;
        wp.data.dispatch( 'core/editor' ).unlockPostSaving( handle );
        wp.data.dispatch( 'core/notices' ).removeNotice( handle );
    }
}

wp.data.subscribe( () => {
    // get presentation
    const textPresentation = wp.data.select( 'core/editor' ).getEditedPostAttribute('meta')['_myprefix_text_metafield'];

    // Lock the post if the presentation is empty.
    lock(
        ! textPresentation,
        'presentation-lock',
        'Please add a presentation text',
    );

    // get the current title
    const postTitle = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'title' );

    // Lock the post if the title is empty.
    lock(
        ! postTitle,
        'title-lock',
        'Please add a title',
    );


    // get the Featured Image
    const featuredImage = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'featured_media' );

    // Lock post if there is no Featured Image selected
    lock(
        featuredImage === 0,
        'featured-image-lock',
        'Please add a featured image',
    );

});

When I write this in the console :

wp.data.select( 'core/editor' ).getEditedPostAttribute('meta')['_myprefix_text_metafield'];

The value returned well the value of my text field.


Solution

  • That could happen when the XHR/AJAX request that fetches post data from the REST API hasn't been fully resolved, so you can't simply access the metadata like that. You need to ensure that getEditedPostAttribute('meta') actually returns an object and only then access the _myprefix_text_metafield property.

    So try with this instead:

    const textPresentation = wp.data.select( 'core/editor' ) // wrapped for brevity
        .getEditedPostAttribute( 'meta' )?._myprefix_text_metafield;
    
    // Lock the post if the presentation is empty.
    lock(
        undefined !== textPresentation && ! textPresentation,
        'presentation-lock',
        'Please add a presentation text'
    );