Skip to content

WordPress’ Block Editor and Custom Post Meta

Quick recap, mostly just for me:

In the classic editor, you have a custom meta box. You hit “Save,” “Publish,” “Update,” etc., it will submit the page; on the back end, you now have access to the various $_POST variables and can use them to update, e.g., (custom) post meta (“custom fields”). Easy peasy.

With Gutenberg (the “block editor”), actual meta boxes are a bit of a hack. Because (on “post submit,” for instance) different parts of the page are updated “dynamically,” i.e., without page refresh, the above no longer holds. Instead, Gutenberg does what it does, and then fires a “second” AJAX request to deal with (and submit) meta boxes’ $_POST variables.

This causes some, uh, weird behavior. Like, a post will already have been published/updated/etc. whenever its “meta fields” are available to the back end. (Another example: in “Share on Mastodon,” I’m looking to add a “custom status” field. Which—well, depending on how the plugin’s set up—isn’t seen until after the post has already been shared. There’s more such examples, unfortunately.)

One way around this is to ditch old-style meta boxes and instead use the block editor’s sidebar(s), or sidebar panels. Those allow you to set post meta that will be saved (or updated) the first time around.

Great! Except that, whenever any—not just yours, but any—meta box is still around (and WordPress’ built-in custom fields “panel” is one such meta box), that second request will still happen, and post meta showing (and thereby showing the old value) in the Custom Fields panel will override (and overwrite) whatever was saved just before.

There’s a way around that, too. Either use hidden custom fields—too bad, I guess, that I typically unhide these, in order to be able to better see/troubleshoot what’s going on—or simply … hide the custom fields panel entirely. So that if, e.g., another plugin inserts its meta box and the custom fields panel was supposed to be open, no values will be overwritten by the second request. The latter is messing with users’ preferences, though. (If they’d previously opted to display the custom fields panel, it’ll just … be gone. At least for the post types we target.)

(Another downside to using Gutenberg’s sidebar panels is that, as long as I want to keep supporting the classic editor, I’ve basically got to maintain two copies of the same code, one in PHP and another in JavaScript.)

Update: I may, after all, stick with classic meta boxes a little longer. Looks like there might be a workaround, where I ignore the first request but only if it comes from the block editor. (This is yet another challenge: 3rd party clients, like mobile apps, also use the REST API, and you don’t want to ignore their requests.)