I am trying to create a Sidebar plugin that stores post meta to be used on the front end. Without getting into the unnecessary details, I need to store all the data as 1 meta entry instead of many rows per post. Here is what I have so far:
// ds-jars.js
const pluginContent = (props) => {
const productData = () => {
const categoryId = createElement( PanelRow, null,
createElement(TextControl, {
label: "Category Name",
value: props.category_id,
onChange: (content) => {
props.set_category_id(content)
},
})
)
const serialId = createElement( PanelRow, null,
createElement( TextControl, {
label: "Serial Number",
value: props.serial_id,
onChange: (content) => {
props.set_serial_id(content)
}
})
)
const productId = createElement( PanelRow, null,
createElement( TextControl, {
label: "Product ID",
value: props.product_id,
onChange: (content) => {
props.set_product_id(content)
}
})
)
return createElement(PluginDocumentSettingPanel, {
title: "Product Data",
name: "ds-jars-productdata",
icon: 'none',
}, categoryId, serialId, productId
)
}
return productData()
}
const selectData = (select) => {
return {
category_id: select("core/editor").getEditedPostAttribute("meta")["category_id"],
serial_id: select("core/editor").getEditedPostAttribute("meta")["serial_id"],
product_id: select("core/editor").getEditedPostAttribute("meta")["product_id"],
name: select("core/editor").getEditedPostAttribute("meta")["name"],
quantity: select("core/editor").getEditedPostAttribute("meta")["quantity"],
color: select("core/editor").getEditedPostAttribute("meta")["color"],
height: select("core/editor").getEditedPostAttribute("meta")["height"],
width: select("core/editor").getEditedPostAttribute("meta")["width"],
depth: select("core/editor").getEditedPostAttribute("meta")["depth"],
pattern: select("core/editor").getEditedPostAttribute("meta")["pattern"],
date_made: select("core/editor").getEditedPostAttribute("meta")["date_made"],
date_updated: select("core/editor").getEditedPostAttribute("meta")["date_updated"],
date_expired: select("core/editor").getEditedPostAttribute("meta")["date_expired"]
}
}
const dispatchData = (dispatch) => {
return {
set_category_id: (value) => {dispatch("core/editor").editPost({meta:{category_id: value} })},
set_serial_id: (value) => {dispatch("core/editor").editPost({meta:{serial_id: value} })},
set_product_id: (value) => {dispatch("core/editor").editPost({meta:{product_id: value} })},
set_name: (value) => {dispatch("core/editor").editPost({meta:{name: value} })},
set_quantity: (value) => {dispatch("core/editor").editPost({meta:{quantity: value} })},
set_color: (value) => {dispatch("core/editor").editPost({meta:{color: value} })},
set_height: (value) => {dispatch("core/editor").editPost({meta:{height: value} })},
set_width: (value) => {dispatch("core/editor").editPost({meta:{width: value} })},
set_depth: (value) => {dispatch("core/editor").editPost({meta:{depth: value} })},
set_pattern: (value) => {dispatch("core/editor").editPost({meta:{pattern: value} })},
set_date_made: (value) => {dispatch("core/editor").editPost({meta:{date_made: value} })},
set_date_updated: (value) => {dispatch("core/editor").editPost({meta:{date_updated: value} })},
set_date_expired: (value) => {dispatch("core/editor").editPost({meta:{date_expired: value} })}
}
}
let fieldSelect = withSelect(selectData)(pluginContent)
let fieldDispatch = withDispatch(dispatchData)(fieldSelect)
registerPlugin( "ds-jars", {
icon: 'store',
render: fieldDispatch
})
Obviously this works but saves each field as its own meta row entry. According to this post: WP 5.3 Supports Object and Array Meta Types in the REST API. I should be able to send an object to the meta field by using an array in for "show_in_rest". I have been able to register the field I want properly using the following:
register_post_meta('', 'ds_product',
array(
'type' => 'object',
'single' => true,
'show_in_rest' => array(
'schema' => array(
'type' => 'object',
'properties' => array(
'category_id' => array('type' => 'string'),
'serial_id' => array('type' => 'string'),
'product_id' => array('type' => 'string'),
'name' => array('type' => 'string'),
'quantity' => array('type' => 'string'),
'color' => array('type' => 'string'),
'height' => array('type' => 'string'),
'width' => array('type' => 'string'),
'depth' => array('type' => 'string'),
'pattern' => array('type' => 'string'),
'date_made' => array('type' => 'string'),
'date_updated' => array('type' => 'string'),
'date_expired' => array('type' => 'string'),
)
)
)
)
);
I am able to manually send an object through with console.log so it seems it is ready for my values to be sent to it as an object. The problem I am having is writing/reading to this meta field using the withSelect/withDispatch functions. How can I send all my values to this meta field "ds_product" using withDispatch? Been struggling with this for a week. I have tried many things the closest I got was using
// Create prop to get data from serialized field
category_id: select("core/editor").getEditedPostAttribute("meta")["ds_product"].category_id
category_id: select("core/editor").getEditedPostAttribute("meta")["ds_product"].serial_id
...
// Update serialized field
set_category_id: (value) => {dispatch("core/editor").editPost({meta:{ds_product:{category_id: value} }})},
set_serial_id: (value) => {dispatch("core/editor").editPost({meta:{ds_product:{serial_id: value} }})},
...
Since they update one at a time the field ends up storing the previously changed value only thus wiping all other data before it. Any help would be hugely appreciated. As a final note I am aware of the dangers/limitations of storing serialized data to the database but I still need it to be done this way. Thanks ahead of time!