Skip to content
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

Proposal: Block Params #49391

Closed
wants to merge 5 commits into from
Closed

Proposal: Block Params #49391

wants to merge 5 commits into from

Conversation

noisysocks
Copy link
Member

@noisysocks noisysocks commented Mar 28, 2023

What & why

This PR experiments with adding params to the block API.

const block = createBlock( { // passing an object to access advanced use-cases
	name: 'core/file',
	attributes: { fileName: file.name },
	innerBlocks: [],
	params: { blobURL: createBlobURL( file ) }, // block params
} );

The params object is like attributes in that it is passed to the block's edit functions for the lifecycle of that block. Unlike attributes, though, params is:

  • Read only. There is no setParams passed to edit.
  • Not serialised. The data in params is not written to the database and does not appear in the markup returned from serialize( block ).
  • Not passed to save. This is to prevent block validation / deprecation issues.

If you consider that blocks are kind of like React components, then you can think of attributes as state and params as props. It's a way of passing data to a block without affecting its state.

The motivation for this is to fix a longstanding issue we've had in Gutenberg which is that we use attributes to store "internal" state in certain blocks. For example an undo level is created when dragging-and-dropping an image or file into the editor because the blob URL is stored in the url attribute while the file is uploaded. I've included a fix for the File block (61ad707) to illustrate how params helps.

I've also included fixes for two other issues to illustrate that there are many uses for such an API:

  • 9a69574 Removing the __internalWidgetId attribute in favour of params. __internalWidgetId is how the widget editor tracks which widget entity should be updated when a block is modified. It's a hack that works because __internalWidgetId does not appear in the block.json and so is filtered out by serialize().
  • d8af0cb Allowing Menu widgets wrapped in a Legacy Widget block to be converted to a Navigation block. This is fixed by having the transform provide the Navigation block with the menu to convert via params.menuId. See Widget Importer: ensure it works with importing menus #47285.

Alternatives

One alternative would be to use attributes but mark them as "private".

"blobUrl": {
	"type": "string",
	"access": "private",
}

The downside of this is that implementation details appear for all to see in block.json.

@github-actions
Copy link

github-actions bot commented Mar 28, 2023

Size Change: +539 B (0%)

Total Size: 1.34 MB

Filename Size Change
build/block-editor/index.min.js 200 kB +262 B (0%)
build/block-library/index.min.js 202 kB +88 B (0%)
build/block-library/style-rtl.css 12.7 kB +11 B (0%)
build/block-library/style.css 12.7 kB +12 B (0%)
build/blocks/index.min.js 51.1 kB -14 B (0%)
build/components/index.min.js 208 kB +19 B (0%)
build/components/style-rtl.css 11.7 kB -20 B (0%)
build/components/style.css 11.7 kB -23 B (0%)
build/data/index.min.js 8.68 kB +61 B (+1%)
build/edit-post/index.min.js 34.8 kB -6 B (0%)
build/edit-site/index.min.js 63 kB +65 B (0%)
build/editor/index.min.js 45.8 kB +10 B (0%)
build/editor/style-rtl.css 3.53 kB -7 B (0%)
build/editor/style.css 3.53 kB -6 B (0%)
build/widgets/index.min.js 7.38 kB +87 B (+1%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 993 B
build/annotations/index.min.js 2.78 kB
build/api-fetch/index.min.js 2.27 kB
build/autop/index.min.js 2.15 kB
build/blob/index.min.js 483 B
build/block-directory/index.min.js 7.2 kB
build/block-directory/style-rtl.css 1.04 kB
build/block-directory/style.css 1.04 kB
build/block-editor/content-rtl.css 4.11 kB
build/block-editor/content.css 4.1 kB
build/block-editor/default-editor-styles-rtl.css 403 B
build/block-editor/default-editor-styles.css 403 B
build/block-editor/style-rtl.css 14.5 kB
build/block-editor/style.css 14.5 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 138 B
build/block-library/blocks/audio/theme.css 138 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 91 B
build/block-library/blocks/avatar/style.css 91 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 587 B
build/block-library/blocks/button/editor.css 587 B
build/block-library/blocks/button/style-rtl.css 628 B
build/block-library/blocks/button/style.css 627 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 113 B
build/block-library/blocks/categories/editor.css 112 B
build/block-library/blocks/categories/style-rtl.css 124 B
build/block-library/blocks/categories/style.css 124 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 406 B
build/block-library/blocks/columns/style.css 406 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 612 B
build/block-library/blocks/cover/editor.css 613 B
build/block-library/blocks/cover/style-rtl.css 1.6 kB
build/block-library/blocks/cover/style.css 1.59 kB
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 138 B
build/block-library/blocks/embed/theme.css 138 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 265 B
build/block-library/blocks/file/style.css 265 B
build/block-library/blocks/file/view.min.js 353 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 984 B
build/block-library/blocks/gallery/editor.css 988 B
build/block-library/blocks/gallery/style-rtl.css 1.55 kB
build/block-library/blocks/gallery/style.css 1.55 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 654 B
build/block-library/blocks/group/editor.css 654 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 830 B
build/block-library/blocks/image/editor.css 829 B
build/block-library/blocks/image/style-rtl.css 652 B
build/block-library/blocks/image/style.css 652 B
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/latest-comments/style-rtl.css 357 B
build/block-library/blocks/latest-comments/style.css 357 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 507 B
build/block-library/blocks/media-text/style.css 505 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 716 B
build/block-library/blocks/navigation-link/editor.css 715 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation/editor-rtl.css 2.13 kB
build/block-library/blocks/navigation/editor.css 2.14 kB
build/block-library/blocks/navigation/style-rtl.css 2.22 kB
build/block-library/blocks/navigation/style.css 2.21 kB
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB
build/block-library/blocks/navigation/view.min.js 447 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 401 B
build/block-library/blocks/page-list/editor.css 401 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 174 B
build/block-library/blocks/paragraph/editor.css 174 B
build/block-library/blocks/paragraph/style-rtl.css 279 B
build/block-library/blocks/paragraph/style.css 281 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 501 B
build/block-library/blocks/post-comments-form/style.css 501 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 134 B
build/block-library/blocks/post-excerpt/style.css 134 B
build/block-library/blocks/post-featured-image/editor-rtl.css 588 B
build/block-library/blocks/post-featured-image/editor.css 586 B
build/block-library/blocks/post-featured-image/style-rtl.css 322 B
build/block-library/blocks/post-featured-image/style.css 322 B
build/block-library/blocks/post-navigation-link/style-rtl.css 153 B
build/block-library/blocks/post-navigation-link/style.css 153 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 281 B
build/block-library/blocks/post-template/style.css 281 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-time-to-read/style-rtl.css 69 B
build/block-library/blocks/post-time-to-read/style.css 69 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 326 B
build/block-library/blocks/pullquote/style.css 325 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 288 B
build/block-library/blocks/query-pagination/style.css 284 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 463 B
build/block-library/blocks/query/editor.css 463 B
build/block-library/blocks/quote/style-rtl.css 222 B
build/block-library/blocks/quote/style.css 222 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 132 B
build/block-library/blocks/read-more/style.css 132 B
build/block-library/blocks/rss/editor-rtl.css 149 B
build/block-library/blocks/rss/editor.css 149 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 408 B
build/block-library/blocks/search/style.css 406 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 234 B
build/block-library/blocks/separator/style.css 234 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 489 B
build/block-library/blocks/site-logo/editor.css 489 B
build/block-library/blocks/site-logo/style-rtl.css 203 B
build/block-library/blocks/site-logo/style.css 203 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.4 kB
build/block-library/blocks/social-links/style.css 1.39 kB
build/block-library/blocks/spacer/editor-rtl.css 332 B
build/block-library/blocks/spacer/editor.css 332 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 433 B
build/block-library/blocks/table/editor.css 433 B
build/block-library/blocks/table/style-rtl.css 651 B
build/block-library/blocks/table/style.css 650 B
build/block-library/blocks/table/theme-rtl.css 157 B
build/block-library/blocks/table/theme.css 157 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 404 B
build/block-library/blocks/template-part/editor.css 404 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 179 B
build/block-library/blocks/video/style.css 179 B
build/block-library/blocks/video/theme-rtl.css 139 B
build/block-library/blocks/video/theme.css 139 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.11 kB
build/block-library/common.css 1.11 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11.6 kB
build/block-library/editor.css 11.6 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/theme-rtl.css 698 B
build/block-library/theme.css 703 B
build/block-serialization-default-parser/index.min.js 1.13 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/compose/index.min.js 12.4 kB
build/core-data/index.min.js 16.3 kB
build/customize-widgets/index.min.js 12.2 kB
build/customize-widgets/style-rtl.css 1.41 kB
build/customize-widgets/style.css 1.41 kB
build/data-controls/index.min.js 663 B
build/date/index.min.js 40.4 kB
build/deprecated/index.min.js 518 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.72 kB
build/edit-post/classic-rtl.css 571 B
build/edit-post/classic.css 571 B
build/edit-post/style-rtl.css 7.6 kB
build/edit-post/style.css 7.59 kB
build/edit-site/style-rtl.css 10.1 kB
build/edit-site/style.css 10.1 kB
build/edit-widgets/index.min.js 17.3 kB
build/edit-widgets/style-rtl.css 4.56 kB
build/edit-widgets/style.css 4.56 kB
build/element/index.min.js 4.95 kB
build/escape-html/index.min.js 548 B
build/format-library/index.min.js 7.26 kB
build/format-library/style-rtl.css 557 B
build/format-library/style.css 556 B
build/hooks/index.min.js 1.66 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.79 kB
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.79 kB
build/keycodes/index.min.js 1.94 kB
build/list-reusable-blocks/index.min.js 2.14 kB
build/list-reusable-blocks/style-rtl.css 865 B
build/list-reusable-blocks/style.css 865 B
build/media-utils/index.min.js 2.99 kB
build/notices/index.min.js 977 B
build/plugins/index.min.js 1.94 kB
build/preferences-persistence/index.min.js 2.23 kB
build/preferences/index.min.js 1.35 kB
build/primitives/index.min.js 960 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 937 B
build/react-i18n/index.min.js 702 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.75 kB
build/reusable-blocks/index.min.js 2.26 kB
build/reusable-blocks/style-rtl.css 265 B
build/reusable-blocks/style.css 265 B
build/rich-text/index.min.js 11.1 kB
build/server-side-render/index.min.js 2.09 kB
build/shortcode/index.min.js 1.52 kB
build/style-engine/index.min.js 1.55 kB
build/token-list/index.min.js 650 B
build/url/index.min.js 3.74 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.8 kB
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 1.09 kB
build/warning/index.min.js 280 B
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.18 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@github-actions
Copy link

github-actions bot commented Mar 28, 2023

Flaky tests detected in 6eb6316.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4558877573
📝 Reported issues:

@talldan
Copy link
Contributor

talldan commented Mar 28, 2023

There is a similar proposal (at least in terms of the 'meta' name) in Custom labelling/naming of blocks in List View.

May need to figure out the right way to marry these two APIs together (or keep them apart).

@getdave
Copy link
Contributor

getdave commented Mar 28, 2023

@noisysocks Just surfacing #43986 in case you missed it or it helps to inform this PR 🙇

There is a similar proposal (at least in terms of the 'meta' name) in #42605

Thanks for flagging. We split out the metadata part in the PR above.

value={ downloadButtonText }
value={
downloadButtonText ??
_x( 'Download', 'button label' )
Copy link
Member

@gziolo gziolo Mar 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noting that this means that the translated Download text will no longer get serialized in the saved content. There is a hack to ensure this value gets set upon insertion using a side effect to avoid validation issues when the user changes the language. It was previously assigned to the default value wrapped with i18n helper.

Ideally, it would be a dynamic token that gets translated to a current locale on both the client and the server.

@gziolo gziolo added [Feature] Block API API that allows to express the block paradigm. [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible labels Mar 28, 2023
@gziolo
Copy link
Member

gziolo commented Mar 28, 2023

@noisysocks and I discussed the idea privately, and I wanted to summarize the talking points here. We definitely need something like that. It’s a great starting point and it should work in most cases based on a quick assessment. A slightly different approach to the same problem worth exploring is to use a proxy wrapper for the value passed when creating a block:

const block = createBlock( { // passing an object to access advanced use-cases
	name: 'core/file',
	attributes: {
		fileName: file.name,
		blobURL: transientAttributeValue( createBlobURL( file ) ),
	},
} );

Behind the scenes we could wrap the value with a proxy object like TransientAttributeValue that would allow us:

  • continue using setAttributes and attributes inside edit without any changes, it would even simplify usage by laveraging the proxy that hides the complexity for devs
  • have a way to detect transient values in the Redux store and to allow skiping storing the change in the undo/redo history
  • prevent saving the post content when the value is still transient, in effect enforce waiting until the value gets replaced with the final one

@noisysocks, expaned on the idea with the following use cases:

Could work! Maybe a bit more complicated (to use) than adding a new property to blocks? But the pattern is cool. I like that it means we could have a few attribute proxy things for different use cases:

  • TransientAttribute - doesn’t get serialised, doesn’t create undo levels
  • NotPersistantAttribiute - doesn’t create undo levels
  • NotCopyableAttribute - doesn’t end up in block when block is cloned or duplicated

Can compose them too which is nice.

We need to discover shortcomings though. There are no perfect solutions 😅

@youknowriad
Copy link
Contributor

TransientAttribute - doesn’t get serialised, doesn’t create undo levels
NotPersistantAttribiute - doesn’t create undo levels
NotCopyableAttribute - doesn’t end up in block when block is cloned or duplicated

Looking at these use-cases. I have some questions:

  • Why isn't it just a property of the attribute definition (it's always better when things are statically analyzable)
  • What's the actual use-case for an attribute that is serializable but doesn't create undo levels?

@gziolo
Copy link
Member

gziolo commented Mar 28, 2023

Looking at these use-cases. I have some questions:

  • Why isn't it just a property of the attribute definition (it's always better when things are statically analyzable)
  • What's the actual use-case for an attribute that is serializable but doesn't create undo levels?

It's all about the values of the attribute at a given time. An Image (File – from the code example, too) block is a great example. When you drag and drop an image from the filesystem, the block editor shows the in-memory version, while uploading it to the server, to improve user experience. This value for the image is local to the machine and can't be accessed by anyone else, so we don't want to serialize it in the saved content, nor keep it in the undo/redo history. We only care about the uploaded URL that gets set as a value when the whole process end. In effect, there isn't a simple way to encode this information in the block attributes definition.

@youknowriad
Copy link
Contributor

One potential solution could be to keep the temporary value in a separate attribute (transient one) and have the block fallback to that one when defined. It feels acceptable to me.

@noisysocks
Copy link
Member Author

noisysocks commented Mar 28, 2023

The two disadvantages I see with making "transient" a property of the attribute definition (in block.json) are:

  • Blocks leak implementation details. Somebody browsing the block.json for core/file would see blobURL in the "attributes" and assume that it's something they can/should use when it is not. There's also backwards compatibility concerns with anything "public".
  • It doesn't work neatly for the __internalWidgetId case because one would have to add __internalWidgetId to every block's definition, supposedly via a registerBlockType filter.

I don't know if it's of any actual practical concern but a nice feature about the approach in this PR as opposed to TransientAttribute or having properties in the attribute definition is that we can not allow data in block.meta to be passed to save() which means there are no deprecation concerns.

I think the three issues I fix in this PR as well as the Pay with PayPal case in #29693 are representative of the problem space and so what I'll do is open a few different PRs that attempt to solve them with different approaches. Then we'll see what we learn.

I'll also learn what I can about #42605. Not sure if it's in the same problem space. Block labels (#42605) are regular attributes and so unrelated to any of this. They're serialised, support undo/redo, copying, etc.

@mcsf
Copy link
Contributor

mcsf commented Apr 20, 2023

TransientAttribute - doesn’t get serialised, doesn’t create undo levels
NotPersistantAttribiute - doesn’t create undo levels
NotCopyableAttribute - doesn’t end up in block when block is cloned or duplicated

It's worth reminding that this exact notion of "transient" attributes was explored back in 2018. The closest PRs are #11504 and #12724 and the proposals were hardly consensual. But mixing transients into regular attributes — something I suggested back then — is something I'm very reticent about now. Like Grzegorz, at the time I was envisioning a broader solution to accommodate not just the instantiation of blocks (i.e. using a seed value like blobUrl with which FileEdit can handle previewing and uploading) but also various automatic/implicit attribute changes that might happen in a block's lifetime.

However, this was before the introduction of entities and the accompanying overhaul of undo/redo (2019). In this new paradigm, we added actions like __unstableMarkNextChangeAsNotPersistent to handle any automatic/implicit attribute change. This greatly reduced the need for a schema-based solution. So we only have the instantiation problem left to address, and for that I think @noisysocks's proposal based on constant params is better, smaller and safer.

@gziolo
Copy link
Member

gziolo commented Apr 21, 2023

One potential solution could be to keep the temporary value in a separate attribute (transient one) and have the block fallback to that one when defined. It feels acceptable to me.

I'm leaning towards the idea shared by @youknowriad where the transient value should be represented as a separate attribute that is never persisted by the block editor. It's a very simple way to apply changes to the existing blocks that use transient values for showing media previews as exercised in #49457. In addition to that, it's a minimal change that adds only a flag to the definition of attributes which is the most convenient way for block developers. The API changes necessary in this PR would be more complex and difficult to explain in the documentation.

@mcsf
Copy link
Contributor

mcsf commented Apr 24, 2023

I'm leaning towards the idea shared by @youknowriad where the transient value should be represented as a separate attribute that is never persisted by the block editor.

In that case I think we should do a formal comparison with previous attempts (#11504 and #12724) to understand what changed (are there new circumstances? or is the new solution different in a meaningful way?).

@noisysocks noisysocks closed this Jun 26, 2023
@Mamaduka Mamaduka deleted the try/block-meta branch July 3, 2024 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block API API that allows to express the block paradigm. [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants