feat: form state select (#11689)
Implements a select-like API into the form state endpoint. This follows the same spec as the Select API on existing Payload operations, but works on form state rather than at the db level. This means you can send the `select` argument through the form state handler, and it will only process and return the fields you've explicitly identified. This is especially useful when you only need to generate a partial form state, for example within the bulk edit form where you select only a subset of fields to edit. There is no need to iterate all fields of the schema, generate default values for each, and return them all through the network. This will also simplify and reduce the amount of client-side processing required, where we longer need to strip unselected fields before submission.
This commit is contained in:
@@ -855,6 +855,7 @@ describe('General', () => {
|
||||
test('should not override un-edited values in bulk edit if it has a defaultValue', async () => {
|
||||
await deleteAllPosts()
|
||||
const post1Title = 'Post'
|
||||
|
||||
const postData = {
|
||||
title: 'Post',
|
||||
arrayOfFields: [
|
||||
@@ -879,6 +880,7 @@ describe('General', () => {
|
||||
],
|
||||
defaultValueField: 'not the default value',
|
||||
}
|
||||
|
||||
const updatedPostTitle = `${post1Title} (Updated)`
|
||||
await createPost(postData)
|
||||
await page.goto(postsUrl.list)
|
||||
@@ -890,10 +892,8 @@ describe('General', () => {
|
||||
hasText: exactText('Title'),
|
||||
})
|
||||
|
||||
await expect(titleOption).toBeVisible()
|
||||
await titleOption.click()
|
||||
const titleInput = page.locator('#field-title')
|
||||
await expect(titleInput).toBeVisible()
|
||||
await titleInput.fill(updatedPostTitle)
|
||||
await page.locator('.form-submit button[type="submit"].edit-many__publish').click()
|
||||
|
||||
|
||||
@@ -269,10 +269,6 @@ export interface Post {
|
||||
* This is a very long description that takes many characters to complete and hopefully will wrap instead of push the sidebar open, lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, voluptatum voluptates. Quisquam, voluptatum voluptates.
|
||||
*/
|
||||
sidebarField?: string | null;
|
||||
/**
|
||||
* This field should only validate on submit. Try typing "Not allowed" and submitting the form.
|
||||
*/
|
||||
validateUsingEvent?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
_status?: ('draft' | 'published') | null;
|
||||
@@ -719,7 +715,6 @@ export interface PostsSelect<T extends boolean = true> {
|
||||
disableListColumnText?: T;
|
||||
disableListFilterText?: T;
|
||||
sidebarField?: T;
|
||||
validateUsingEvent?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
_status?: T;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { Payload } from 'payload'
|
||||
import type { Payload, User } from 'payload'
|
||||
|
||||
import { buildFormState } from '@payloadcms/ui/utilities/buildFormState'
|
||||
import path from 'path'
|
||||
import { createLocalReq } from 'payload'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
import type { NextRESTClient } from '../helpers/NextRESTClient.js'
|
||||
@@ -12,6 +14,7 @@ import { postsSlug } from './collections/Posts/index.js'
|
||||
let payload: Payload
|
||||
let token: string
|
||||
let restClient: NextRESTClient
|
||||
let user: User
|
||||
|
||||
const { email, password } = devUser
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
@@ -22,8 +25,7 @@ describe('Form State', () => {
|
||||
// Boilerplate test setup/teardown
|
||||
// --__--__--__--__--__--__--__--__--__
|
||||
beforeAll(async () => {
|
||||
const initialized = await initPayloadInt(dirname)
|
||||
;({ payload, restClient } = initialized)
|
||||
;({ payload, restClient } = await initPayloadInt(dirname))
|
||||
|
||||
const data = await restClient
|
||||
.POST('/users/login', {
|
||||
@@ -35,6 +37,7 @@ describe('Form State', () => {
|
||||
.then((res) => res.json())
|
||||
|
||||
token = data.token
|
||||
user = data.user
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
@@ -43,5 +46,97 @@ describe('Form State', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it.todo('should execute form state endpoint')
|
||||
it('should build entire form state', async () => {
|
||||
const req = await createLocalReq({ user }, payload)
|
||||
|
||||
const postData = await payload.create({
|
||||
collection: postsSlug,
|
||||
data: {
|
||||
title: 'Test Post',
|
||||
},
|
||||
})
|
||||
|
||||
const { state } = await buildFormState({
|
||||
id: postData.id,
|
||||
collectionSlug: postsSlug,
|
||||
data: postData,
|
||||
docPermissions: {
|
||||
create: true,
|
||||
delete: true,
|
||||
fields: true,
|
||||
read: true,
|
||||
readVersions: true,
|
||||
update: true,
|
||||
},
|
||||
docPreferences: {
|
||||
fields: {},
|
||||
},
|
||||
documentFormState: undefined,
|
||||
operation: 'update',
|
||||
renderAllFields: false,
|
||||
req,
|
||||
schemaPath: postsSlug,
|
||||
})
|
||||
|
||||
expect(state).toMatchObject({
|
||||
title: {
|
||||
value: postData.title,
|
||||
initialValue: postData.title,
|
||||
},
|
||||
updatedAt: {
|
||||
value: postData.updatedAt,
|
||||
initialValue: postData.updatedAt,
|
||||
},
|
||||
createdAt: {
|
||||
value: postData.createdAt,
|
||||
initialValue: postData.createdAt,
|
||||
},
|
||||
renderTracker: {},
|
||||
validateUsingEvent: {},
|
||||
blocks: {
|
||||
initialValue: 0,
|
||||
requiresRender: false,
|
||||
rows: [],
|
||||
value: 0,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('should use `select` to build partial form state with only specified fields', async () => {
|
||||
const req = await createLocalReq({ user }, payload)
|
||||
|
||||
const postData = await payload.create({
|
||||
collection: postsSlug,
|
||||
data: {
|
||||
title: 'Test Post',
|
||||
},
|
||||
})
|
||||
|
||||
const { state } = await buildFormState({
|
||||
id: postData.id,
|
||||
collectionSlug: postsSlug,
|
||||
data: postData,
|
||||
docPermissions: undefined,
|
||||
docPreferences: {
|
||||
fields: {},
|
||||
},
|
||||
documentFormState: undefined,
|
||||
operation: 'update',
|
||||
renderAllFields: false,
|
||||
req,
|
||||
schemaPath: postsSlug,
|
||||
select: {
|
||||
title: true,
|
||||
},
|
||||
})
|
||||
|
||||
expect(state).toStrictEqual({
|
||||
title: {
|
||||
value: postData.title,
|
||||
initialValue: postData.title,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it.todo('should skip validation if specified')
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user