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
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);