fix(ui): allow json fields to be updated externally (#11371)
### What? Unable to update json fields externally. For example, calling `setValue` on a json field would not be reflected in the admin panel UI. ### Why? JSON fields use the monaco editor to manage state internally, so programmatically updating the value in state does not change the internal value. ### How? Set a ref when the user updates the value and then unset the ref after the change is complete. Inside the hook that watches `value`, if the value changed and the change came from the system (i.e. a programmatic change) refresh the editor by adjusting its key prop. If the change was made by the user, there is no need to refresh the editor. Fixes https://github.com/payloadcms/payload/issues/10819
This commit is contained in:
38
test/fields/collections/JSON/AfterField.tsx
Normal file
38
test/fields/collections/JSON/AfterField.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
'use client'
|
||||
|
||||
import { useField } from '@payloadcms/ui'
|
||||
|
||||
export function AfterField() {
|
||||
const { setValue } = useField({ path: 'customJSON' })
|
||||
|
||||
return (
|
||||
<button
|
||||
id="set-custom-json"
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
setValue({
|
||||
users: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'John Doe',
|
||||
email: 'john.doe@example.com',
|
||||
isActive: true,
|
||||
roles: ['admin', 'editor'],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Jane Smith',
|
||||
email: 'jane.smith@example.com',
|
||||
isActive: false,
|
||||
roles: ['viewer'],
|
||||
},
|
||||
],
|
||||
})
|
||||
}}
|
||||
style={{ marginTop: '5px', padding: '5px 10px' }}
|
||||
type="button"
|
||||
>
|
||||
Set Custom JSON
|
||||
</button>
|
||||
)
|
||||
}
|
||||
@@ -103,4 +103,24 @@ describe('JSON', () => {
|
||||
'"foo.with.periods": "bar"',
|
||||
)
|
||||
})
|
||||
|
||||
test('should update', async () => {
|
||||
const createdDoc = await payload.create({
|
||||
collection: 'json-fields',
|
||||
data: {
|
||||
customJSON: {
|
||||
default: 'value',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
await page.goto(url.edit(createdDoc.id))
|
||||
const jsonField = page.locator('.json-field #field-customJSON')
|
||||
await expect(jsonField).toContainText('"default": "value"')
|
||||
|
||||
const originalHeight = (await page.locator('#field-customJSON').boundingBox())?.height || 0
|
||||
await page.locator('#set-custom-json').click()
|
||||
const newHeight = (await page.locator('#field-customJSON').boundingBox())?.height || 0
|
||||
expect(newHeight).toBeGreaterThan(originalHeight)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -67,6 +67,16 @@ const JSON: CollectionConfig = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'customJSON',
|
||||
type: 'json',
|
||||
admin: {
|
||||
components: {
|
||||
afterInput: ['./collections/JSON/AfterField#AfterField'],
|
||||
},
|
||||
},
|
||||
label: 'Custom Json',
|
||||
},
|
||||
],
|
||||
versions: {
|
||||
maxPerDoc: 1,
|
||||
|
||||
@@ -1474,6 +1474,15 @@ export interface JsonField {
|
||||
| boolean
|
||||
| null;
|
||||
};
|
||||
customJSON?:
|
||||
| {
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| unknown[]
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -3165,6 +3174,7 @@ export interface JsonFieldsSelect<T extends boolean = true> {
|
||||
| {
|
||||
jsonWithinGroup?: T;
|
||||
};
|
||||
customJSON?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user