Gutenberg default initial values for FocalPointPicker

I am trying use <FocalPointPicker /> in <PluginDocumentSettingPanel /> and almost everything working as it should, but I have troubles when creating a new post. I am getting this warning:

Warning: Received NaN for the value attribute.

As I understand it occur because post meta isn’t created yet. I solved this by adding update_post_meta during post creation. But I think there should be a better solution using pure React.

This is my code:

// in init.php
add_action('init','register_my_post_meta');
function register_my_post_meta() {
    $args_img = array(
        'type' => 'object',
        'single' => true,
        'show_in_rest' => array(
            'schema' => array(
                'type'  => 'object',
                'properties' => array(
                        'url' => array(
                        'type' => 'url',
                    ),
                        'width' => array(
                        'type' => 'number',
                    ),
                        'height' => array(
                        'type' => 'number',
                    ),
                        'id' => array(
                        'type' => 'number',
                    ),
                ),
            ),
        ),
    );

    $args_focal = array(
        'type' => 'object',
        'single' => true,
        'show_in_rest' => array(
            'schema' => array(
                'type'  => 'object',
                'properties' => array(
                        'x' => array(
                        'type' => 'number',
                    ),
                        'y' => array(
                        'type' => 'number',
                    ),
                ),
            ),
        ),
    );
    register_post_meta( '', 'img', $args_img );
    register_post_meta( '', 'focalPoint', $args_focal );
}
// in index.js
const { registerPlugin } = wp.plugins;
const { PluginDocumentSettingPanel } = wp.editPost;
const { withSelect, withDispatch } = wp.data;
const { MediaUpload, MediaUploadCheck } = wp.blockEditor;
const { Button, FocalPointPicker } = wp.components;



let PhotoControl = ({img, focalPoint, handleImgChange, handleFocalChange}) =>(
  <MediaUploadCheck>
    {!!img["url"] &&
      <FocalPointPicker
        url={ img["url"] }
        value={ focalPoint }
        onChange={ focalPoint => handleFocalChange(focalPoint)}
      />
    }
    {!img["url"] &&
      <MediaUpload
         title="My Image"
         onSelect={
           img => handleImgChange(img)
         }
         allowedTypes={['image']}
         value={ img }
         render= { ( { open } ) => (
            <Button
             id={'image-upload'}
             onClick={open}>
                 { ! img["url"] && "upload image" }
            </Button>
         ) }
     />
    }
  </MediaUploadCheck
);

PhotoControl = withSelect(
  (select) => {
      return {
          img: select('core/editor').getEditedPostAttribute('meta')['img'],
          focalPoint: select('core/editor').getEditedPostAttribute('meta')['focalPoint']
      }
  }
)(PhotoControl);

PhotoControl = withDispatch(
  (dispatch) => {
      return {
          handleImgChange: (value) => {
              dispatch('core/editor').editPost({ meta: { img:{
                "url": value.url,
                "width": value.width,
                "height": value.height,
                "id": value.id
              } })
          }
          handleFocalChange: (value) => {
              dispatch('core/editor').editPost({ meta: { focalPoint: value } })
          }
      }
  }
)(PhotoControl);

const PluginWithFocalpoint = () => {
  return(
    <PluginDocumentSettingPanel>
      <PhotoControl />
    </PluginDocumentSettingPanel>

  );
}
registerPlugin( 'plugin-with-focalpoint', { render: PluginWithFocalpoint, icon: ' ' } );

And here my temporary solution:

// in init.php
function create_meta_for_new_posts($post_id, $post, $update) {
    if (empty(get_post_meta( $post_id, 'focalPoint' ))) {
        update_post_meta( $post_id, 'focalPoint', array("x"=>0.5,"y"=>0.5) );
    }
}
add_action( 'wp_insert_post', 'create_meta_for_new_posts', 10, 3 );

1 Answer
1

Ok, I found the solution by myself. Inside withSelect it is needed to assign default value if getEditedPostAttribute is empty.

// Helper function to check if received meta object is empty or not
function isEmpty(obj) {
  for(var key in obj) {
      if(obj.hasOwnProperty(key))
          return false;
  }
  return true;
}

PhotoControl = withSelect(
  (select) => {
      let myFocal = select('core/editor').getEditedPostAttribute('meta')['focalPoint'];
      if(isEmpty(myFocal)) { focal={ "x": 0.5, "y": 0.5 }; } // Solution is here. If is empty object assign default values.
      return {
          img: select('core/editor').getEditedPostAttribute('meta')['img'],
          focalPoint: myFocal
      }
  }
)(PhotoControl);

Leave a Comment