Hi all ๐.
Thanks in advance for any help, links and code examples you are able to provide.
The purpose of this GitHub issue is to establish a list of the current issues that exist between ACF & Gutenberg so that we may ask those reading to contribute constructive solutions, code examples, links, ideas and help. This is not a discussion board for thoughts or opinions, nor is it an attempt to provoke such comments.
If you are able to share knowledge, thank you, and please remember to provide references when possible. Please let me know if you would like this ticket moved to the ACF GitHub repo instead.
โ๏ธ Update: Compatibility issues have been split into individual GitHub issues for streamlined comments and ease of maintenance.
Status: Fixed in 5.7.9 but requires further improvement.
Link: https://github.com/AdvancedCustomFields/acf/issues/111
Status: Broken. Researching solutions.
Link: https://github.com/AdvancedCustomFields/acf/issues/112
Status: Broken. Researching solutions.
Link: https://github.com/AdvancedCustomFields/acf/issues/113
Status: Fixed in 5.7.9 but requires further improvement.
https://github.com/AdvancedCustomFields/acf/issues/114
Thanks for getting this far and again for providing any help on the above issue.
ACF
Hi Thanks for opening the issue.
How do we listen for changes to the following post attributes?
The main way to listen to data changes or update data in Gutenberg is to use the data module (wp.data
). Ideally we shouldn't rely on DOM anymore as the DOM is not an official API and subject to change over time.
In order to subscribe to changes you use wp.data.subscribe
. You retrieve the data using selectors and you update the data using actions.
Here are some links that could be helpful here:
How can we hide and show metaboxes? Is CSS ok for this?
How can we update the "Show on Screen" check boxes to match?
How can we hide / show the following "elements"?
Can we still achieve this via CSS, or can we use the JS API?
These "hide on screen" settings update via the "Dynamic metaboxes" feature, so we need the ability to hide an "element" and then show it later if need be.
These questions are all related and have the same answers. So you probably can't continue to use CSS to target these elements. Even if you probably can do it for some of them, I would consider a hack as the DOM is not an official API and if the element in question is rendered with React (most of them), it can get rerendered which overrides any DOM change you can make imperatively.
That said, we have a list of "selectors" and "actions" to show/hide these elements using the data module:
What can we "hook" into to prevent the post from being submit in order to validate via AJAX and then re-submit?
We do provide data module actions whether a post is not savable at any given moment, which will allow disable the publish buttons in consequence.
How can we get all the $_POST data about the post (title, content, etc)?
Same reply to the initial question, you can retrieve all this informations from the data module. https://github.com/WordPress/gutenberg/blob/master/packages/editor/src/store/effects/posts.js#L61-L85 This snippet should give you an idea of what Gutenberg does to retrieve the Data sent to the save API request. you can use the exact same selectors to retrieve this data.
Is there an API for displaying an error message in Gutenberg?
There's an API to display notice messages (similar to the notices Gutenberg itself displays when you save a post...)
You can checkout the list of selectors and actions available here
Issue 4: Position โhighโ
This has been discussed and the decision was to not support this hook/filter at the moment mainly because the goal of Gutenberg is to allow visual editing which means in phase2 and beyond we may be able to edit the whole page/site using the Gutenberg editor. This means for instance the post title becomes a block, the post content becomes a block with inner blocks... you'd be able to reorder those, add sidebar elements.... This means that allowing the edit_form_after_title
would not be possible as everything in the main canvas is a block and we can't include random DOM elements between them. This has been discussed here
Issue 6: Metabox Saving
Having a MetaBox on the editor will automatically trigger a second save request for backwards compatibility reasons, there's no way for Gutenberg "to know" what the meta-box is doing and most metabox rely on the post.php
hooks to save their changes. You can still use the data module to update the post object used by gutenberg ( editPost
action) which will make sure these data changes are handled by the REST API request but this won't prevent the post.php call.
To avoid having to trigger another save function, I'd suggest avoiding the meta box API entirely and will suggest using the Plugin API. Several parts of the Gutenberg UI offer what we call "Slots". For example you can register a Sidebar Slot, to have a sidebar dedicated to your own plugin, a modal, ...
Read more here:
I hope this helps.
@chrisvanpatten - can we make sure that the most important points from @youknowriad's answers are included in our docs? I think we have many of those areas covered already, but some of them need to be updated with more details. We might also want to add a section which general guidelines on how to build plugins.
Thinking out loud, one could use a similar method as the metaboxes to render the after title section in PHP, then use a react portal to hoist it inside a block created by ACF JS and inserted at the beginning of the relevant post types, then strip out that block. Keeping in mind that blocks can choose to store their data in post meta rather than post content
Issue 3 is big blocker for myself as well in integrating with Gutenberg with just meta boxes (and probably blocks too...).
Currently, the integration with meta boxes works fine for my plugin info is saved and validation passes/fails but there's no feedback.
If the minimum required info is not valid, then we revert the post to draft during the save process and put out an admin notice. There doesn't seem to be a clean way to do this...
I would have hoped that this would still be done fully server-side so the result of the save attempt is modified before sent back to the editor.
Hi @elliotcondon! Looking forward to spending some time helping out with ACF! I'll start by answering as many of your questions here as I can. I'll then move over into the ACF repo and hopefully help out there with some contributions. Feel free to hit me up at any time either here or on the Making WordPress Slack.
Could you let me know the current status of the issues that you've outlined in your original comment here? Are they all outstanding, or have some been addressed in ACF?
I've done my best to elaborate on all the questions above. I've used ๐ to mark likely action items for me on the Gutenberg side of things. Hope it helps!
- How do we listen for changes to the following post attributes?
- page_template
- page_parent
- post_format
- post_terms
If we have a React component then we can make it update when there are changes by wrapping it with withSelect()
. Otherwise, we'll need to do this manually using subscribe()
. I suspect that ACF will need to use the latter approach as it's built using jQuery.
let pageTemplate;
wp.data.subscribe( () => {
const newPageTemplate = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'template' );
if ( pageTemplate !== newPageTemplate ) {
console.log( 'Page template has changed!' );
pageTemplate = newPageTemplate;
}
} );
- How do we get these values via the JS api?
select()
and getEditedPostAttribute()
is what we'll need here to access this data. The REST API reference is useful here for figuring out what post attributes are available.
const { getEditedPostAttribute } = wp.data.select( 'core/editor' );
const pageTemplate = getEditedPostAttribute( 'template' );
const pageParent = getEditedPostAttribute( 'parent' );
const postFormat = getEditedPostAttribute( 'format' );
const postTerms = getEditedPostAttribute( 'taxonomy_name' ); // e.g. 'tags', 'categories'
- How can we hide and show metaboxes? Is CSS ok for this?
Dispatching removeEditorPanel()
is likely the most resilient thing to use here. Meta box panel IDs are meta-box-
followed by the ID of the meta box.
// Hides the 'postcustom' meta box
wp.data.dispatch( 'core/edit-post' ).removeEditorPanel( 'meta-box-postcustom' );
- How can we update the "Show on Screen" check boxes to match?
By this do you mean the checkboxes that appear in the _Options_ modal?
If so, then those can be toggled by using toggleEditorPanelEnabled()
.
// Toggles the 'my-box' meta box
wp.data.dispatch( 'core/edit-post' ).toggleEditorPanelEnabled( 'meta-box-my-box' );
- How can we hide / show the following "elements"?
- Permalink
- Content Editor (not sure if this is possible now)
- Excerpt
- Discussion
- Comments
- Revisions
- Slug
- Author
- Format
- Page Attributes
- Featured Image
- Categories
- Tags
- Send Trackbacks
Some panels can be removed by dispatching removeEditorPanel()
.
wp.data.dispatch( 'core/edit-post' ).removeEditorPanel( 'post-link' ); // Permalink
wp.data.dispatch( 'core/edit-post' ).removeEditorPanel( 'post-excerpt' ); // Excerpt
wp.data.dispatch( 'core/edit-post' ).removeEditorPanel( 'discussion-panel' ); // Discussion
wp.data.dispatch( 'core/edit-post' ).removeEditorPanel( 'page-attributes' ); // Page Attributes
wp.data.dispatch( 'core/edit-post' ).removeEditorPanel( 'featured-image' ); // Featured Image
wp.data.dispatch( 'core/edit-post' ).removeEditorPanel( 'post-status' ); // Status & Visibility
๐ We'll need to expand this API so that the rest of your use cases are covered: Comments, Revisions, Slug, Author, Format, Categories, Tags, Send Trackbacks. We also will need to improve the documentation here.
Not sure what you mean by disabling Content Editor. Is that a panel?
- Can we still achieve this via CSS, or can we use the JS API?
Using CSS will do the job here but it's not an official API that we support. That is, we might change a CSS selector in the future without any warning.
- These "hide on screen" settings update via the "Dynamic metaboxes" feature, so we need the ability to hide an "element" and then show it later if need be.
๐ For this we will likely will need to change the removeEditorPanel()
API so that panels can be 'un-removed' later.
- What can we "hook" into to prevent the post from being submit in order to validate via AJAX and then re-submit?
Post saving can be disabled and enabled by dispatching lockPostSaving()
and unlockPostSaving()
.
// Prevent the post from being saved
wp.data.dispatch( 'core/editor' ).lockPostSaving( 'acf' );
// Allow the post to be saved
wp.data.dispatch( 'core/editor' ).unlockPostSaving( 'acf' );
One approach to get this ACF feature working with Gutenberg might be to:
lockPostSaving()
. Likewise, if the request says that the attributes are valid, then call unlockPostSaving()
.
- How can we get all the
$_POST
data about the post (title, content, etc)?
select()
and getEditedPostAttribute()
are what we want again for this. The REST API reference is useful here for figuring out what post attributes are available.
const { getEditedPostAttribute } = wp.data.select( 'core/editor' );
const title = getEditedPostAttribute( 'title' );
const content = getEditedPostAttribute( 'content' );
- How can we re-submit the form after validation is complete?
I don't think this is practical because of how meta boxes are implemented in Gutenberg. I suggest looking into an approach like the one outlined above.
- Is there an API for displaying an error message in Gutenberg?
Yes, the Notices API is what we'll want here. Namely, createErrorNotice()
.
wp.data.dispatch( 'core/notices' ).createErrorNotice( 'Something is not good!' );
- What solutions are there to render a custom metabox location?
As Riad mentioned above, the 'edit_form_after_title'
hook isn't something that we support because our vision is that eventually the page title will be just another block which can be re-arranged and manipulated.
Right now we only support 'normal'
and 'side'
as metabox locations. Is there a location that we could add that would work better for this ACF use case? ๐ It's possible that we could look at adding more locations provided that they align with Gutenberg's long term vision.
Perhaps this will be best in its own issue, but I would like to have a constructive discussion about design options for metaboxes
Yes, such a discussion is probably best left to a follow-up issue that has a Design label.
Think of metaboxes as sidebar panels, much like the "Excerpt" panel. They are important, and should be styled to match.
Is there a way we can append data to the "JSON API save post request" and hook into that request via PHP (similar to the "save_post" action) to submit the $_POST data?
We're running into some of the limitations of the metabox API here. Gutenberg only implements support for metaboxes with a view towards maintaining backwards compatibility. It's expected that in the medium to long term, plugins will move towards other APIs (e.g. Slot/Fill, Plugins) to implement their functionality.
For example, ACF could implement React components that render the UI for editing Custom Fields. These components could use the WordPress component library to achieve a native look and feel. This UI could then be slotted into parts of the Gutenberg editor e.g. the sidebar using our Plugins API.
Would it be helpful if I put together an example on how ACF could use our APIs to render a Gutenberg-native UI in the sidebar for editing ACF Custom Fields?
@noisysocks This may be a little off topic but I just had to comment. After over a week of stumbling around in the dark trying to figure out how to add an admin notice because the documentation on pretty much everything is woefully lacking, in a single comment you managed to shed some much needed light on interacting with this component and several other things. It's amazing what a few lines of simple code and some simple explanations can do for us idiots that are not already entrenched in the GB code.
Glad I could help you out @Hube2. Agree that documentation is something we need to work on.
@noisysocks Thanks for your help with the above questions.
I've gone ahead and created a unique GitHub issue for each of the major items. This should make it a bit easier to follow the conversations.
Please find links to these GitHub issues in the "edited" original topic above.
@youknowriad @noisysocks Thanks a lot for your explanation. We are having similar issues with Gutenberg for our Meta Box plugin. 2 biggest issues are conditional logic (e.g. dynamic meta boxes as described here) and validation.
The conditional logic part seems to be doable with the getEditedPostAttribute
API. I was looking into the docs but couldn't find it.
Validation is kind of more complicated thing. We're using HTML5 validation (such as required
attribute) and JavaScript validation (using jQuery validation library). Do you have any suggestion on that?
Validation is kind of more complicated thing. We're using HTML5 validation (such as required attribute) and JavaScript validation (using jQuery validation library). Do you have any suggestion on that?
@rilwis: I'm assuming that you want to disable post saving and publishing when there is a validation error? One approach might be to add an event listener that runs when there is a validation error. When this happens, call wp.data.dispatch( 'core/editor' ).lockPostSaving( 'your-plugin-name-goes-here' )
. When the errors have been fixed, call wp.data.dispatch( 'core/editor' ).unlockPostSaving( 'your-plugin-name-goes-here' )
.
I've gone ahead and created a unique GitHub issue for each of the major items. This should make it a bit easier to follow the conversations.
Thanks @elliotcondon, good idea. Let's continue discussion over in the linked issues.
@noisysocks Thanks. That would work for JS validation. HTML5 validation seems to be not supported in issue #5883.
+1, following...
@noisysocks Thanks. You saved me hours of search. However, I am still not able to remove the editor panel for Status & Visibility
, I have tried and post-status but the Status & Visibility panel remains.
Most helpful comment
Hi Thanks for opening the issue.
The main way to listen to data changes or update data in Gutenberg is to use the data module (
wp.data
). Ideally we shouldn't rely on DOM anymore as the DOM is not an official API and subject to change over time.In order to subscribe to changes you use
wp.data.subscribe
. You retrieve the data using selectors and you update the data using actions.Here are some links that could be helpful here:
These questions are all related and have the same answers. So you probably can't continue to use CSS to target these elements. Even if you probably can do it for some of them, I would consider a hack as the DOM is not an official API and if the element in question is rendered with React (most of them), it can get rerendered which overrides any DOM change you can make imperatively.
That said, we have a list of "selectors" and "actions" to show/hide these elements using the data module:
We do provide data module actions whether a post is not savable at any given moment, which will allow disable the publish buttons in consequence.
Same reply to the initial question, you can retrieve all this informations from the data module. https://github.com/WordPress/gutenberg/blob/master/packages/editor/src/store/effects/posts.js#L61-L85 This snippet should give you an idea of what Gutenberg does to retrieve the Data sent to the save API request. you can use the exact same selectors to retrieve this data.
There's an API to display notice messages (similar to the notices Gutenberg itself displays when you save a post...)
You can checkout the list of selectors and actions available here
This has been discussed and the decision was to not support this hook/filter at the moment mainly because the goal of Gutenberg is to allow visual editing which means in phase2 and beyond we may be able to edit the whole page/site using the Gutenberg editor. This means for instance the post title becomes a block, the post content becomes a block with inner blocks... you'd be able to reorder those, add sidebar elements.... This means that allowing the
edit_form_after_title
would not be possible as everything in the main canvas is a block and we can't include random DOM elements between them. This has been discussed hereHaving a MetaBox on the editor will automatically trigger a second save request for backwards compatibility reasons, there's no way for Gutenberg "to know" what the meta-box is doing and most metabox rely on the
post.php
hooks to save their changes. You can still use the data module to update the post object used by gutenberg (editPost
action) which will make sure these data changes are handled by the REST API request but this won't prevent the post.php call.To avoid having to trigger another save function, I'd suggest avoiding the meta box API entirely and will suggest using the Plugin API. Several parts of the Gutenberg UI offer what we call "Slots". For example you can register a Sidebar Slot, to have a sidebar dedicated to your own plugin, a modal, ...
Read more here:
I hope this helps.