-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
API Question: Copy / Paste Handler Filter for Blocks #23377
Comments
Hi! This is an interesting question. I'll try to answer piece by piece:
Short answer: no, there isn't. The closest would be the
One way to look at this is to invert the relationship: rather than setting up a filter to automatically change/strip certain data, can the block's Before I explain what I mean by the above, let's discuss this one first:
I did my best not to focus on the example at hand :) but I think it's a little unavoidable, because use cases inform our needs. Block attributes really are meant to be an expression of what the block is, and every attribute should be essential to how the block looks and behaves. Under this light, it's hard not to think of identifiers as something different. And, indeed, Gutenberg's own Here is the use case that I found that might be the closest to an ID but remain a "meaningful" block attribute: the optional HTML anchor for an element. const isAnchorUnique = useSelect( ( select ) => select( 'core/block-editor' ) .getBlocks() .filter( ( { attributes: { anchor: otherAnchor } } ) => otherAnchor !== undefined && otherAnchor === anchor ).length <= 1 ); useEffect( () => { if ( isAnchorUnique ) { return; } console.log( 'Heading anchor', anchor, 'is already in use. Unsetting value…' ); setAttributes( { anchor: undefined } ); }, [ anchor ] ); This "works" but actually doesn't, because it necessarily breaks Undo. Indeed, However, it does provide some insight on the problem at hand: let the user know that there is a duplicate anchor and ask the them to fix this. It's the same principle as for mis-leveled headings in a document or low-contrast colour combinations — the editor doesn't dare to "fix" automatically, it informs and recommends. This could be extended to HTML anchors by patching So, in the end, I'd like to hear more about the intended use cases. When would you really need this? What are these IDs that need to be stripped, and could they be hinting at an underlying problem? I don't mean to be blocking a possible new API, I just want to be super mindful about how we approach extending APIs. :) |
Hi @mcsf Thank you for your attention on this 🙌. You have answered everything quite nicely and the isAnchorUnique code example is great. This approach is exactly how ACF is currently handling unique block attributes when duplicating a block. Although perfect for a "unique per post" solution, the limitation of this approach becomes apparent when wanting a "unique per site" value. Okay, let me explain with more detail why this is important for ACF, and other 3rd party developers. There is a strong philosophy used throughout the ACF plugin, derived from WordPress itself, which is the relational concept of Objects and Meta. Each Object (post, term, user) contains a unique ID, which can be used to target the correct Meta data. To integrate this philosophy (needed for ACF functions to work) into blocks, we opted to give each block a persistent unique ID, which is saved in the I mentioned that we are already using an "is unique" solution in our edit function. This takes care of the conflicts when duplicating a block - easy. The problem we now face is when a user copy's a block from one post and pastes it on another post. Without a filter in place for this event, we can't (in any performant manor) detect that this is actually a new block which requires a new unique ID. A filter on "copy" (to unset the ID) or a filter on "paste" (to generate a new ID) would solve our problem 100%. Now, for a non "ID" related scenario. Imagine a block type that displays a colorful tile like the CSS-Tricks Popular this month one. The developer expects authors to insert or copy/paste this block around the site quite often and wants to ensure some variety in the gradients colors. Specific filters for "new block", "copy block" and "paste block" would allow a simple way to generate new gradients at the right times (not on every "edit" render). I hope these examples are enough to get this feature request considered. It would help out a lot of ACF block users 👍. Thanks |
Thanks for all the details, @elliotcondon! I think this could be a worthwhile addition. It does raises a few UX questions, especially as far as user expectations and consistency go. For instance, what happens when a user uses the Duplicate action instead of Copy followed by Paste? Actually, this question made me find #20237, which happens to be a useful cross-reference with many parallels with the present issue. I'm also thinking that, rather than a wide "filter" to intercept certain block actions, a simpler and more effective interface for this might be a new property in block attributes: {
align: {
type: 'string',
},
acfId: {
type: 'string',
portable: false,
},
…
|
@mcsf This As you mention, the benefit here is a more "universal" approach that covers more use-cases. The downside is that it may require more architecture & strategy as it will have global implications. This ultimately increases the chance of it getting buried in the already large number of feature requests. Thinking back to the "classic way" of customizing WordPress, how do the Gutenberg development team feel about adding in actions / filters in general? Is there a tendency to avoid them? I'm a firm believer that the hook system in WordPress is what allowed the development community to thrive and would love to see hooks for all the major events in block editing such as duplicate, copy, paste, insert. I can see these working in a similar way to the editor.BlockEdit or blocks.getSaveContent.extraProps. Let me know what I can do to help aid this improvement 👍 |
I'd be happy to offer a real-world use case where having a stable unique block ID is extremely helpful: an accordion block. An accordion block needs an ID for at least two reasons:
While editors certainly can specify a custom ID, I want to automatically provide a unique ID for every accordion block so that using a "pretty" ID is optional. Due to the nature of anchor links, they need to be both unique and stable. And similar to the OP, when copied or duplicated, the IDs need to be regenerated. This isn't just an issue I've run into but is also mentioned in this accordion block. I also imagine that a Table of Contents block would run into a similar issue in wanting to offer stable page anchors is a high priority. |
As @mcsf notes, there's currently no API that nicely solves this use case. There's discussion about creating such an API in #29693. There's been several proposals but unfortunately none that have gained a broad consensus among contributors. It's a big change to the block API so everyone understandably wants to get it right. In the meantime you might be able to make use of the same hack that the widgets editor uses which is store the ID in an attribute that isn't defined in the block's I'm going to close this help request as answered (though I appreciate it's not a satisfying answer 😀) and let's use #29693 to track the creation of a better API for this. |
Hi team,
A quick technical question for you: Is there a way [via the Block API] to customize a block's
props.attributes
during the copy and past event handler?For example, a developer may want their block instance to contain a unique identifier. If a block is copied & pasted (or duplicated), the
props.attributes
will also be duplicated causing two blocks to share the same identifier. 👉 This is just an example, and not a request for clarity onprops.clientId
.Perhaps there is a filter, or a way to hook in somewhere and customize the data? I've searched through the plugin source code but haven't found anything obvious yet.
Thanks in advance.
The text was updated successfully, but these errors were encountered: