fix(ui): copy & pasting block content duplicates array items in editor UI#15941
Merged
GermanJablo merged 1 commit intopayloadcms:mainfrom Mar 13, 2026
Merged
Conversation
GermanJablo
approved these changes
Mar 13, 2026
Contributor
GermanJablo
left a comment
There was a problem hiding this comment.
This is a really good PR! Thank you so much for the test and the detailed description!
Contributor
|
🚀 This is included in version v3.79.1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What?
When copying a block row that contains an array field and pasting it into a new block of the same type, the array items in the pasted block appeared doubled in the UI (e.g. 3 items → 6 items) immediately after pasting. After saving, the duplicates disappeared since the persisted data was always correct, making this a pure UI state issue.
Why?
When pasting a block row,
mergeFormStateFromClipboardintentionally skips.idfields to avoid overwriting the target block's identity. However, the condition clipboardPath.endsWith('.id') was too broad. It skipped all.idpaths, including nested array item IDs inside the block (e.g.ctas.0.buttons.0.id).This left the pasted block's array field with the correct rows metadata (copied from clipboard, containing the source block's IDs), but no corresponding .id form state entries. On the next onChange, the server rebuilt form state from the submitted data, couldn't match any array rows by ID (since the
.idfields were missing), and marked all of them asaddedByServer: true. When the server response was merged back viamergeServerFormState, those rows were appended to the already-existing client rows doubling them.How?
Changed the skip condition from matching any
.idpath to matching only the direct block row ID:- (!pasteIntoField && clipboardPath.endsWith('.id'))+ (!pasteIntoField && clipboardPath ===${pathToReplace}.id)Nested IDs now fall through to the existing ID-regeneration logic, which assigns fresh IDs and updates the
rowsmetadata. The server can then match the rows by their new IDs, so no duplication occurs on merge. The target block's direct ID is still protected from being overwritten.A unit test was added to
mergeFormStateFromClipboard.spec.tscovering the exact scenario.Fixes #15940