-
Notifications
You must be signed in to change notification settings - Fork 32
Connect block attributes with custom fields via UI #176
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Conversation
917b150
to
8d471bc
Compare
I think there's a minor UX glitch with regard to the tools panel and link/unlink button: AFAIU, we should change two things here:
(This is based on how I observed the UX pattern to work e.g. for the existing margin panel in the style tab of the block inspector.) |
But, in that case, if you have the four of them unlinked, and want to reset only the image title or alt, you will need to reset every of them at once and set one by one again, right? It's better to keep consistency, but as we change the number of toolsitem, that is the default behaviour. I'll take a look at how is implemented for margin and styles. Thanks @ockham! |
63e9e91
to
7fa68ab
Compare
assets/src/js/bindings/sources.js
Outdated
const handleDateFieldValue = ( fieldValue, fieldConfig ) => { | ||
if ( ! fieldValue ) { | ||
return ''; | ||
} | ||
|
||
return dateI18n( fieldConfig?.display_format, fieldValue ) || ''; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be interested in making date_picker
fields work with Core's Date block (that I'm currently working on). That block will allow binding to its datetime
attribute, which will be using this format. The user can use the block inspector to set the format that the date is rendered with (this is a feature of the Date block that already exists).
However, AFAICS, the SCF source will always return the date using the display_format
that's set in SCF options, meaning that the Date block might receive the date in a format that it won't understand ❌
In this particular case, one solution would be to allow binding the Date block's format
attribute to a source, and to have SCF expose its format. This could be a fairly elegant solution, as it would allow both using SCF's format, but also setting a custom format from within the Date block. (We would need to allow unlinking individual bound attributes, however.)
This might work well enough in the case of date fields, but might not scale to other cases. In the bigger picture, this is a question of who decides the formatting of a given piece of information. An alternative approach would be for SCF to always just provide a standardized "raw" format, and to leave formatting up to the individual block that it is bound to. IMO, this makes some sense, as it encapsulates the data layer in SCF, and leaves the formatting to the presentational layer (i.e. the blocks). However, it would mean that SCF's own format settings will be ignored, and some data won't look pretty when bound to a more "primitive" block (e.g. binding datetime
to a paragraph block).
I was wondering how the question of formatting was previously considered in the context of Block Bindings. For example, so far, all examples of Block Bindings use args: { key: ... }
to select a given source field for binding; was the idea that format
could be supplied as an additional arg? (E.g. args: { key: date, format: 'M j, Y' }
?
We probably don't have to answer this for this PR, but it might be good to keep in mind for our next steps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, it would mean that SCF's own format settings will be ignored, and some data won't look pretty when bound to a more "primitive" block (e.g. binding datetime to a paragraph block).
I guess we could auto-convert paragraphs bounded to a datetime field to that date block to avoid that. But then it would not be compatible with future "shortblocks". My opinion is that the format value defined on the field has been widely used, so it should be the default one, and then the block should be capable to override that format option.
That way we wouldn't break backwards compatibility neither. We could for sure update the source with more args. The key one was a convention from the beginning of the project.
assets/src/js/bindings/sources.js
Outdated
const handleNumericFieldValue = ( fieldValue, attribute, getMedia ) => { | ||
if ( attribute === 'content' ) { | ||
return fieldValue.toString() || ''; | ||
} | ||
|
||
// For image fields or numeric values, try to resolve as media | ||
const imageObj = getMedia( fieldValue ); | ||
return resolveImageAttribute( imageObj, attribute ); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd love if we could restructure this a bit. IMO, it feels a bit backwards that when given a numeric value, we have to guess if it's an image ID, when we have higher-level information about field types available at the callsite. (A similar note applies to handleObjectFieldValue
.)
I'll quickly try out locally what that would look like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please! Totally agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more or less what I have in mind: At the top level, a switch
for all possible SCF field types. It's still incomplete since I'm not yet totally familiar with all the possible ways they are mapped to block attributes.
switch ( fieldType ) {
case 'text':
case 'textarea':
return fieldValue || '';
case 'number':
if ( attribute === 'content' ) {
return fieldValue.toString() || '';
}
break;
case 'image':
// fieldValue is a (numeric) image ID.
const imageObj = getMedia( fieldValue );
return resolveImageAttribute( imageObj, attribute );
case 'date_picker':
if ( ! fieldValue ) {
return '';
}
return dateI18n( fieldConfig?.display_format, fieldValue ) || '';
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 2c96d62.
Sure, my opinion is that the |
assets/src/js/bindings/sources.js
Outdated
// Special fallback: if we're looking for 'content' and no content property exists (or is falsy), | ||
// but there's a 'url' property, use that instead | ||
if ( attribute === 'content' && fieldValue.url ) { | ||
return fieldValue.url; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this for images?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Image doesn't have 'content' as a bindable attribute, lets change that.
Updated in 60976f6
Fixed in 89d69ff |
Maybe 🤔 Plus I guess I need to file a bug report against Gutenberg, since it seems that |
I have a prototype working, but is adding all values parsed by SCF to the types endpoint, ending with maybe too much information. I will instead try to extend acf object data to include the formatted value. |
Per discussion via DM, I've pushed a fix for the date issue: 718af07 |
This one has been fixed. |
What
The PR allows to connect block attributes with custom fields via UI. Is still experimental, as I have not yet tested with any field type that can be created. In a future PR we can add an advanced view, using DataViews.
The image block will only search for image type fields, and all their attributes can be bound at once, just selecting the image field.
The paragraph, heading, and button blocks will only work with an initial set of items set in this variable:
Screenshare
Screen.Recording.2025-07-08.at.18.04.35.mov