From 37c945b95b0a1b23f95ba5cd1f56352022ac7aba Mon Sep 17 00:00:00 2001 From: Jessica Rynkar <67977755+jessrynkar@users.noreply.github.com> Date: Wed, 25 Jun 2025 14:44:00 +0100 Subject: [PATCH] fix(ui): custom row labels on arrays should not be removed on field duplication (#12895) ### What? This fix prevents custom row labels being removed when duplicating array items. ### Why? Currently, when you have an array with custom row labels, if you create a new array item by duplicating an existing item, the new item will have no custom row label until you refresh the page. ### How? During the `duplicate` process, we remove any react components from the field state. This change intentionally re-adds the `RowLabel` if one exists. #### Reported by client --- packages/ui/src/forms/Form/fieldReducer.ts | 6 ++++ test/fields/collections/Array/e2e.spec.ts | 41 ++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/packages/ui/src/forms/Form/fieldReducer.ts b/packages/ui/src/forms/Form/fieldReducer.ts index 2260a2d94..cb5ccf33d 100644 --- a/packages/ui/src/forms/Form/fieldReducer.ts +++ b/packages/ui/src/forms/Form/fieldReducer.ts @@ -146,6 +146,12 @@ export function fieldReducer(state: FormState, action: FieldAction): FormState { duplicateRowMetadata.id = new ObjectId().toHexString() } + if (rowsMetadata[rowIndex]?.customComponents?.RowLabel) { + duplicateRowMetadata.customComponents = { + RowLabel: rowsMetadata[rowIndex].customComponents.RowLabel, + } + } + const duplicateRowState = deepCopyObjectSimpleWithoutReactComponents(rows[rowIndex]) if (duplicateRowState.id) { diff --git a/test/fields/collections/Array/e2e.spec.ts b/test/fields/collections/Array/e2e.spec.ts index 1102e574e..b63e58dbe 100644 --- a/test/fields/collections/Array/e2e.spec.ts +++ b/test/fields/collections/Array/e2e.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable playwright/no-wait-for-selector */ import type { Page } from '@playwright/test' import { expect, test } from '@playwright/test' @@ -112,6 +113,46 @@ describe('Array', () => { await expect(customRowLabel).toHaveCSS('text-transform', 'uppercase') }) + test('should render custom RowLabel after duplicating array item', async () => { + const label = 'test custom row label' + const updatedLabel = 'updated custom row label' + await loadCreatePage() + await page.locator('#field-rowLabelAsComponent >> .array-field__add-row').click() + + await page.locator('#field-rowLabelAsComponent__0__title').fill(label) + + const customRowLabel = page.locator( + '#rowLabelAsComponent-row-0 >> .array-field__row-header > :text("test custom row label")', + ) + + await expect(customRowLabel).toBeVisible() + await expect(customRowLabel).toHaveCSS('text-transform', 'uppercase') + + const rowActionsButton = page.locator('#rowLabelAsComponent-row-0 .array-actions__button') + await rowActionsButton.click() + + const duplicateButton = page.locator( + '#rowLabelAsComponent-row-0 .popup__scroll-container .array-actions__duplicate', + ) + await expect(duplicateButton).toBeVisible() + await duplicateButton.click() + + await expect(page.locator('#rowLabelAsComponent-row-1')).toBeVisible() + await expect( + page.locator( + '#rowLabelAsComponent-row-1 >> .array-field__row-header > :text("test custom row label")', + ), + ).toBeVisible() + + await page.locator('#field-rowLabelAsComponent__1__title').fill(updatedLabel) + const duplicatedRowLabel = page.locator( + '#rowLabelAsComponent-row-1 >> .array-field__row-header > :text("updated custom row label")', + ) + + await expect(duplicatedRowLabel).toBeVisible() + await expect(duplicatedRowLabel).toHaveCSS('text-transform', 'uppercase') + }) + test('should render default array field within custom component', async () => { await loadCreatePage()