Custom metaboxes are used extensively in WordPress for layout purposes as well as data structure. However, they don’t necessarily — in fact they rarely — save to the meta
key’s array of objects when they’re added to the WordPress REST API and can’t be used by Gutenberg’s built in meta
attribute.
How can we use Gutenberg with them? Should we look at how they work now and replicate that functionality exactly? It’s necessary to keep in mind that this data will be edited in the context of the editor where the user has no knowledge — and cannot be expected to need any knowledge — of how the data is stored or managed.
Let’s take a step back and think first what we need and expect Gutenberg to do for any given block.
- retrieve the data
- update on save
- update to a revision whenever a revision is made
- delete the block data when the post is deleted
- delete the block data when a block is deleted unless it is explicitly a shared block and there is another block using the same data
- have the block data be independent of any other block data unless it is explicitly a shared block
And then look at the minimum of what we expect our metaboxes to do right now:
- retrieve the data
- save/update on save
- delete the data if a metabox is cleared or in the case of repeating fields or the core custom fields, removed
How do we combine the two?
Retrieving the data is straightforward. Retrieve it and display it, done.
Saving and updating the data when the post is saved also works much the same in both, phew. For revisions, users will expect to be able to revert to the previous version created with all the data they entered there — again, users cannot be expected to differentiate between blocks which store their data in the content and those which store it elsewhere. (The fact that custom metabox plugins don’t do this out of the box is not an excuse to not do this here; the user experience will be much different and it’s more a bug than a feature of those plugins.)
If we look at deletion, yes, pretty much the same. There is one additional case with postmeta — it is specific to one post. We can have data shared within the same post and not across different posts (use case: add a post specific note to the top and bottom of a post). In that case, we wouldn’t want to delete the data. One note: it could be argued that simply not showing the data on the front end is enough but I strongly disagree with this. Don’t leave orphaned data in the database with no way to edit or delete it.
Once we know what we want to do, then we worry about implementation. This raises some interesting questions:
- do we store postmeta revisions in the database? The postmeta table has a tendency towards bloat anyway, this would really add to it. Maybe we could store it in the attributes then when reverting to a revision, update the parent post’s postmeta.
- how do we show that a block has shared data with another block in the same post?
- (other things you thought of that I haven’t)
To explore some of these issues and get a feel for how I expect it to work, I wrote a block as a test case. It retrieves and saves the data on save and most revisions (see the notes). When I wrote it, I completely forgot about deleting, I’ll do that later. It uses React components with the most basic state management (ie no Redux and look, it doesn’t need it here yet, Dan Abramov says so 🙂 ).
This is by no means a thorough post, it’s simply a collection of my thoughts after playing around with it. Gutenberg has the potential to be absolutely brilliant but it needs time and testing through various use cases so that when it is finally released in core, it is robust enough to handle anything people throw at it.
Leave a Reply