WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.5k stars 4.2k forks source link

inner-blocks sync not applying attribute changes #66840

Open namjul opened 1 day ago

namjul commented 1 day ago

Here is a simplified case of a block using useInnerBlocksProps

registerBlockType(metadata.name, {
  edit() {
    const blockProps = useBlockProps();
    const innerBlocksProps = useInnerBlocksProps(blockProps, {
      allowedBlocks: ['core/paragraph', 'core/image'],
      template: [
        ['core/paragraph', { className: 'text-lg' }],
      ],
      templateLock: 'all'
    });

    return <div {...innerBlocksProps} />;
  },

  save() {
    const blockProps = useBlockProps.save();
    const innerBlocksProps = useInnerBlocksProps.save(blockProps);

    return <div {...innerBlocksProps} />;
  }
})

When i change the className attribute (or any other custom attribute field, so it's unrelated to css!) an existing block does not pick up on it. So when i make attributes updates (tree updates work) to my blocks, meaning the inner-blocks template prop, the user won't see the changes.

-      template: [['core/paragraph', { className: 'text-lg' }]],
+      template: [['core/paragraph', { className: 'text-xs' }]],

Which means i need to remove the block and readd it to have the changes in.

This seems to be an issue with custom blocks and any core block.

After debugging i landed on the synchronizeBlocksWithTemplate function which seems to only sync inner-blocks but not attributes in:

https://github.com/WordPress/gutenberg/blob/ab6e729daf775ee6065a48c210826af8281a0842/packages/blocks/src/api/templates.js#L98

Would on line 98 including attributes make this work?

-return { ...block, innerBlocks };
+return { ...block, attributes, innerBlocks };

If this is by design, my question would be how attributes in the inner-blocks template prop are to be conceptualized. Are they only used for initial state? If so how is deploying of custom blocks that update the useInnerBlocksProps template prop possible without the friction of replacing them manually?

sarthaknagoshe2002 commented 11 hours ago

@namjul The synchronizeBlocksWithTemplate function in gutenberg/packages/blocks/src/api/templates.js is mainly designed to manage the structure (or "tree") of inner blocks rather than individual attribute changes. In other words, its purpose is to keep the block hierarchy synchronized rather than modify existing content attributes, as that might lead to unexpected and potentially disruptive changes.

The line you identified:

return { ...block, innerBlocks };

includes only the innerBlocks, not attributes, as part of this intent. If you add attributes here:

return { ...block, attributes, innerBlocks };

it would indeed synchronize attributes on subsequent loads. However, this could be problematic because users expect that, once they customize a block’s attributes (like changing a paragraph’s text size or style), those values will persist independently of template changes.

namjul commented 9 hours ago

thank you, that lands.

i am recognizing that what i was looking for was to have the "invalid block notification + update button" appear when only attributes change.