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.
This commit is contained in:
Jacob Fletcher
2024-11-22 11:43:48 -05:00
committed by GitHub
parent 27acdaee7a
commit ae6c71b3b5
2 changed files with 58 additions and 2 deletions

View File

@@ -25,6 +25,14 @@ export const traverseFields = <T>(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 = <T>(args: {
break
case 'group':
// falls through
case 'tabs':
if (!result[fieldName]) {
result[fieldName] = {}
@@ -100,8 +108,9 @@ export const traverseFields = <T>(args: {
})
break
case 'relationship':
case 'relationship':
// falls through
case 'upload':
// Handle `hasMany` relationships
if (fieldSchema.hasMany && Array.isArray(incomingData[fieldName])) {

View File

@@ -169,6 +169,53 @@ describe('Collections - Live Preview', () => {
expect(mergedData._numberOfRequests).toEqual(0)
})
it('— arrays - can clear all rows', async () => {
const initialData: Partial<Page> = {
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<Page> = {
title: 'Test Page',