fix(ui): awaits form state before rendering conditional fields (#9933)

When a condition exists on a field and it resolves to `false`, it
currently "blinks" in and out when rendered within an array or block
row. This is because when add rows to form state, we iterate over the
_fields_ of that row and render their respective components. Then when
conditions are checked for that field, we're expecting `passesCondition`
to be explicitly `false`, ultimately _rendering_ the field for a brief
moment before form state returns with evaluated conditions. The fix is
to set these fields into local form state with a new `isLoading: true`
prop, then display a loader within the row until form state returns with
its proper conditions.
This commit is contained in:
Jacob Fletcher
2024-12-13 11:42:52 -05:00
committed by GitHub
parent 9c8cdea4b3
commit 796df37461
14 changed files with 157 additions and 63 deletions

View File

@@ -92,6 +92,49 @@ const ConditionalLogic: CollectionConfig = {
condition: ({ groupSelection }) => groupSelection === 'group2',
},
},
{
name: 'enableConditionalFields',
type: 'checkbox',
},
{
name: 'arrayWithConditionalField',
type: 'array',
fields: [
{
name: 'text',
type: 'text',
},
{
name: 'textWithCondition',
type: 'text',
admin: {
condition: (data) => data.enableConditionalFields,
},
},
],
},
{
name: 'blocksWithConditionalField',
type: 'blocks',
blocks: [
{
slug: 'blockWithConditionalField',
fields: [
{
name: 'text',
type: 'text',
},
{
name: 'textWithCondition',
type: 'text',
admin: {
condition: (data) => data.enableConditionalFields,
},
},
],
},
],
},
],
}

View File

@@ -541,6 +541,26 @@ describe('fields', () => {
const fieldRelyingOnSiblingData = page.locator('input#field-reliesOnParentGroup')
await expect(fieldRelyingOnSiblingData).toBeVisible()
})
test('should not render conditional fields when adding array rows', async () => {
await page.goto(url.create)
const addRowButton = page.locator('.array-field__add-row')
const fieldWithConditionSelector =
'input#field-arrayWithConditionalField__0__textWithCondition'
await addRowButton.click()
const wasFieldAttached = await page
.waitForSelector(fieldWithConditionSelector, {
state: 'attached',
timeout: 100, // A small timeout to catch any transient rendering
})
.catch(() => false) // If it doesn't appear, this resolves to `false`
expect(wasFieldAttached).toBeFalsy()
const fieldToToggle = page.locator('input#field-enableConditionalFields')
await fieldToToggle.click()
await expect(page.locator(fieldWithConditionSelector)).toBeVisible()
})
})
describe('tabs', () => {