From ae6c71b3b5b09ad2f0bc4fe9bc29a3f3eea50dce Mon Sep 17 00:00:00 2001 From: Jacob Fletcher Date: Fri, 22 Nov 2024 11:43:48 -0500 Subject: [PATCH] fix(live-preview): client-side live preview cannot clear all array rows (#9439) When using Client-side Live Preview, array fields are unable to clear all their rows. This is because `reduceFieldsToValues` sets the array's value as 0 within form-state when no rows exist, as opposed to an empty array as one might expect. For now, we can simply handle this data shape within Live Preview's merge logic. In the future we may want to take to consider changing the behavior of empty arrays within form-state itself. --- packages/live-preview/src/traverseFields.ts | 13 +++++- test/live-preview/int.spec.ts | 47 +++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/packages/live-preview/src/traverseFields.ts b/packages/live-preview/src/traverseFields.ts index 271ff5f00b..86064e5f08 100644 --- a/packages/live-preview/src/traverseFields.ts +++ b/packages/live-preview/src/traverseFields.ts @@ -25,6 +25,14 @@ export const traverseFields = (args: { switch (fieldSchema.type) { case 'array': + if ( + !incomingData[fieldName] && + incomingData[fieldName] !== undefined && + result?.[fieldName] !== undefined + ) { + result[fieldName] = [] + } + if (Array.isArray(incomingData[fieldName])) { result[fieldName] = incomingData[fieldName].map((incomingRow, i) => { if (!result[fieldName]) { @@ -85,7 +93,7 @@ export const traverseFields = (args: { break case 'group': - + // falls through case 'tabs': if (!result[fieldName]) { result[fieldName] = {} @@ -100,8 +108,9 @@ export const traverseFields = (args: { }) break - case 'relationship': + case 'relationship': + // falls through case 'upload': // Handle `hasMany` relationships if (fieldSchema.hasMany && Array.isArray(incomingData[fieldName])) { diff --git a/test/live-preview/int.spec.ts b/test/live-preview/int.spec.ts index 0b744c89b6..4df7b919ad 100644 --- a/test/live-preview/int.spec.ts +++ b/test/live-preview/int.spec.ts @@ -169,6 +169,53 @@ describe('Collections - Live Preview', () => { expect(mergedData._numberOfRequests).toEqual(0) }) + it('— arrays - can clear all rows', async () => { + const initialData: Partial = { + title: 'Test Page', + arrayOfRelationships: [ + { + id: '123', + relationshipInArrayMonoHasOne: testPost.id, + }, + ], + } + + const mergedData = await mergeData({ + depth: 1, + fieldSchema: schemaJSON, + incomingData: { + ...initialData, + arrayOfRelationships: [], + }, + initialData, + serverURL, + returnNumberOfRequests: true, + collectionPopulationRequestHandler, + }) + + expect(mergedData.arrayOfRelationships).toEqual([]) + expect(mergedData._numberOfRequests).toEqual(0) + + // do the same but with arrayOfRelationships: 0 + + const mergedData2 = await mergeData({ + depth: 1, + fieldSchema: schemaJSON, + incomingData: { + ...initialData, + // @ts-expect-error eslint-disable-next-line + arrayOfRelationships: 0, // this is how form state represents an empty array + }, + initialData, + serverURL, + returnNumberOfRequests: true, + collectionPopulationRequestHandler, + }) + + expect(mergedData2.arrayOfRelationships).toEqual([]) + expect(mergedData2._numberOfRequests).toEqual(0) + }) + it('— uploads - adds and removes media', async () => { const initialData: Partial = { title: 'Test Page',