-
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
[Block Attributes]: Add support for non-duplicable block attributes #32604
Conversation
This tested as advertised for me, but just a couple of questions:
|
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.
Thanks for working on this @stacimc !
I've commented on the issue about a possible approach I'd been thinking about and wanted to share here as well: #29693 (comment)
It involves __experimentalRole
and __experimentalGetBlockAttributesNamesByRole
util.
Bringing the comment from @ntsekouras for better readability:
There is also a relevant comment from @talldan:
Just wanted to bring one consideration. The name |
Definitely agree. I considered something like 'private' or 'internal' but those have technical implications of their own. |
packages/blocks/src/api/utils.js
Outdated
export function __experimentalSanitizeBlockAttributes( | ||
name, | ||
attributes, | ||
sanitizeUniqueAttributes = false |
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.
Instead of passing a boolean
value as an argument, maybe passing an optional object with explicit name would be better?
__experimentalSanitizeBlockAttributes(
name,
attributes,
// What does it mean?
true
)
__experimentalSanitizeBlockAttributes(
name,
attributes,
{ sanitizeUniqueAttributes: true } // clearer
)
__experimentalSanitizeBlockAttributes(
name,
attributes,
{ shouldSanitizeUniqueAttributes: true } // Even better with explicit boolean-like prefix
)
However, I wonder if instead of passing an additional option here, maybe we can just create another function for this?
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.
Agreed -- the named option is a big improvement. I initially thought to create another function for this (since as @glendaviesnz pointed out, de-duping is also a bit out of place as part of 'sanitize' functionality), but it's a bit rough on code duplication. I can take another stab at refactoring here if we go with this approach.
type: 'string', | ||
unique: true |
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'm wondering if we can just create a new type called ID
(Borrowed from graphql). By definition, it should be a serializable, unique, non-human-readable string. Users can transform it as a number if they wish, but I think string is a good default.
I don't understand how default value could be useful in this case though 🤔. Ideally, unique should mean that the value should be unique across the app, and default values break that rule. I understand sometimes it's necessary in the current architecture though, like when pressing Enter
in a block to create two new blocks while destroying the original one.
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 think the current types are taken from JSON schema.
- https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#type-validation
- https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.6.1.1
It might be ok to deviate from that, I don't know whether there are any definite type restrictions in other parts of the codebase or the REST API. Certainly what's in the blocks package is pretty easy to change.
(edit: this is where I read that -
gutenberg/packages/blocks/src/api/parser.js
Lines 65 to 74 in 7428d7e
/** | |
* Returns true if value is of the given JSON schema type, or false otherwise. | |
* | |
* @see http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.25 | |
* | |
* @param {*} value Value to test. | |
* @param {string} type Type to test. | |
* | |
* @return {boolean} Whether value is of type. | |
*/ |
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.
My initial idea was to do something like this. I abandoned the approach for the same reason @talldan pointed out, and because making an id
type creates much stronger expectations of enforcing uniqueness.
When I raised the issue, for my purposes it was sufficient to make attributes non-duplicable rather than strictly unique, an easier bar to clear. It's pretty clear that the naming in the current implementation conflates these ideas, so I've renamed the attribute key to duplicable
.
When will be this merged? |
The use of `unique` implies strict uniqueness across blocks of the same type, which is not actually enforced here. For clarity the key is changed to `duplicable` and the logic inverted.
0914b1c
to
9999bfc
Compare
Hasn't this approach been considered at all? It involves similar logic with this one ( |
Description
Closes #29693
This PR adds the ability to mark block attributes as
unique
, such that they will not be copied on block duplication. The goal is to allow blocks to use attributes to store unique properties that persist across page loads (unlikeclientId
).For just one example, the Jetpack
Pay with Paypal
block uses aproductId
attribute to identify the actual product record referenced by the block. This data is meant to be internal to the block and should not be exposed to the user. When the user duplicates the block, we want to copy the other attributes used to store price info and other details, but create a brand new product record/productId
.The behavior is opt-in, so blocks do not have to explicitly set
unique: false
. By default all attributes will continue to be copied on duplication.Notes
unique
the best name for this attribute field?duplicable
, but the conditional logic is simpler/clearer if the field isfalse
by default (ie, it's confusing that an attribute is considered 'duplicable' if the field is explicitly set to true or if it not defined).private
, to suggest that it should not be copied. My concern is this, likeunique
, may be an overloaded term.How has this been tested?
You can test by adding
unique: true
to any block attribute, but the JetpackPay with Paypal
block is a particularly illustrative example. Update its block registration inindex.js
:productId
s.Screenshots
Types of changes
Checklist:
*.native.js
files for terms that need renaming or removal).