Description
Note
This is an integral part of the block API #41236
At WCEU contributor day I brought up an idea to a few people on how we could connect blocks and custom fields in a compelling way. In the early days, we had explored a "meta" block attribute source that allowed block authors to create blocks consuming data from post meta. It worked alright but the behavior predated some of the latest block API affordances — like entity handling — and had the limitation of being accessible only for block developers. The other limitation was that we didn't have enough knowledge of how the final html output should render to recreate it on the server, so the PHP output was handled ad hoc on the blocks that consumed fields. This new approach can overcome both obstacles.
The way it'd work is by connecting attributes from normal static blocks (content on paragraph, url on image, and so on) to meta keys instead of serializing their content. So far so good. The crucial difference is that it doesn't require a new custom block with a custom attribute but leverages the built-in blocks as the primary interface. This means we can work out a UI in the block inspector that just needs to handle the connection but doesn't need to support editing nor extrinsic validation because the block itself takes care of it through its normal setAttribute
flow. For example, updating a meta key for an image url would be as easy as dragging an image into the connected image block for a user. This also means patterns would just work out of the box transparently — a user can insert a pattern they like and map the heading block content to a field, the image source to another field, and so on. The edit UI for updating content remains the same.
To overcome the need to rebuild the html on the server we can employ the source declaration as a tag delimiter if we pair it with the new tag processor.
"content": {
"type": "string",
"source": "html",
"selector": "p",
"default": "",
"__experimentalRole": "content"
},
The gist of it is that the way a block declares how to query a serialized source can also function as an indication of how to reassemble that attribute properly. The implementation can thus reutilize an existing API contract instead of introducing a new syntax for tokens. (See #39831.)
Proposal
- The
selector
functions as a token placement, so we don't need additional syntax. The tag processor can find the element and we reconstructinnerHtml
entirely as it's just a simple composition of<$selector>$field</$selector>
. This means we don't need the full block recipe from save because we are just replacing specific attributes. - Since we are just dealing with block attributes, block variations can be created on demand for convenience.
- Transforming between blocks can retain the connection as long as they are valid transforms (so a paragraph using "book author" meta can be turned into a heading using "book author" meta).
- Users should be able to create and assign fields on the fly through the inspector UI, which right now is blocked by the
show_in_rest
requirement (only meta fields registered with show in rest would be available to pick from). - We can probably reduce the amount of specific blocks needed (post title, etc) down the road as we have discussed previously, as long as variations can have namespace aliases.
- This mechanic can help us simplify the various approaches to The
wp:pattern
block #48458 as it bypàsses the need for additional syntax.
Activity
[-]Custom Field 🔗 Blocks[/-][+]Custom fields 🔗 Blocks[/+]joshuatf commentedon Jun 21, 2023
@mtias Love this proposal! Would the above also work for blocks that are form elements?
The new product editor being worked on in Woo is form-based but composed via blocks, I'm wondering if the
<$selector>$field</$selector>
approach would work for an element like a checkbox or any data type that is not strictly presentational.This could be a misunderstanding on my part of how this API is intended to work, so please correct me if I'm misunderstanding how it's meant to be used.
tkapler commentedon Jul 10, 2023
In my opinion:
How i imagine it?
IMO the easiest way would redefinition of shortcodes or implementing e.g. "curly brackets shortcode".
So you can put anywhere [my-custom-field-name] (or {my-custom-field-name} and it would replace it with the the value of my-custom-field-name meta or value of that "shortcode" defined programatically
or I can put there [my-custom-field-name format:hhmmss] and it would use format hhmmss that is defined somewhere (some default list of format will be provided)
And in Gutenberg, it would look like some highlighted

mtias commentedon Jul 12, 2023
@tkapler that's a different enterprise than this issue encapsulates, you can see the ongoing discussions about inline dynamic tokens in #39831
gregoirenoyelle commentedon Jul 24, 2023
Hi @youknowriad
I use more and more this plugin and it works quite well.
https://wordpress.org/plugins/display-a-meta-field-as-block/
You should have a look.
It’s very useful when you need to make some advanced FSE templates. And you can use ACF meta.
tresorama commentedon Jul 31, 2023
Elementor Dynamic Data
I like the UX of how Elementor Pro let you use "Custom Field".
Here is a demo the UX https://www.youtube.com/watch?v=OWUbJrRq7jI
Considerations
1
I think that the Elementor way is applicable only to "dynamic block" ( Gutenberg Blocks that are saved to DB inside "post_content" as JSON data and ALWAYS rendered to HTML on page request phase, as opposed to "static block" that are saved in DB as HTML after being rendered in React side as HTML in the creation phase ) due to their dynamic nature.
2
While custom fields with "string" data type are easy to handle, some other custom field types are instead difficult and it's impossible to anticipate real usage.
I'm thinking of "ACF Repeater", or "ACF Gallery".
These complex fields are usually saved as JSON objects (that can include array inside it).
3
Using a custom field inside the Block Editor require 2 distinctive phases.
Data Value Extraction
, which handles getting data value from DB.Data Rendering
, that is consuming the value with Gutenberg BlockRaw Idea
Single data type
Meaning "string", "number" data type, that can be cast to string and rendered easily.
The Gutenberg Block let the user get the data with a new Button "Dynamic Data" placed in the Block Toolbar, which on click shows a dropdown of custom field names.
An input lets the user also define a nested path in case it's needed, in a JS dot notion fashion (
object.property.subProperty
).Multiple data
In the case of an array of things, something similar to the Query Loop is required.
So a new
ForEach
Gutenberg Block can be used to extract/read the array from the custom field, and then "innerBlocks" of the "ForEach" are treated as the item template, which is repeated for every item of the array."ForEach" block provides extracted data with React Context (or similar) to its children.
Children block of "ForEach" use the same strategy to get custom field data as described in Single data type, with the difference that new values are available thanks to "ForEach" extraction.
An alternative name for the "ForEach" block could be "CustomFieldLoop" to resemble the "QueryLoop" one.
Meanwhile the Meta Field Plugin mentioned by @gregoirenoyelle is the "best at the moment" for what I found...
mtias commentedon Aug 3, 2023
@tresorama with the original proposal it'd work for any block type, including static blocks that serialize as html.
tresorama commentedon Aug 3, 2023
So the user, after changing the custom field value must manually re-save the post content where it's used?
mtias commentedon Aug 3, 2023
No, it's a dynamic value, only the first save (when you connect the block to the field) is necessary.
33 remaining items