Skip to content

Commit 519a3c6

Browse files
authored
fix: get field by path for blocks (#14984)
It's currently not possible to use `getFieldByPath` to find a field nested within a block. For example: ```ts // This return undefined const fieldInBlock = getFieldByPath({ path: 'blocks.block2.text2' , fields: [ { type: 'blocks', name: 'blocks', blocks: [ { slug: 'block1', fields: [ { name: 'text1', type: 'text', }, ], }, { slug: 'block2', fields: [ { name: 'text2', type: 'text', }, ], }, ], } ] }) ``` This is because the function is ignoring block slugs and looping over each block's fields until one is found. Except they are never found because the path is not trimmed for the next iteration. If the same field exists across different blocks, I would also imagine the wrong schema could get matched.
1 parent 446cbb1 commit 519a3c6

2 files changed

Lines changed: 54 additions & 12 deletions

File tree

packages/payload/src/utilities/getFieldByPath.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,30 @@ const fields = flattenAllFields({
6060
},
6161
],
6262
},
63+
{
64+
type: 'blocks',
65+
name: 'blocks',
66+
blocks: [
67+
{
68+
slug: 'block1',
69+
fields: [
70+
{
71+
name: 'text1',
72+
type: 'text',
73+
},
74+
],
75+
},
76+
{
77+
slug: 'block2',
78+
fields: [
79+
{
80+
name: 'text2',
81+
type: 'text',
82+
},
83+
],
84+
},
85+
],
86+
},
6387
],
6488
})
6589

@@ -105,4 +129,13 @@ describe('getFieldByPath', () => {
105129
expect(assert_7.pathHasLocalized).toBe(true)
106130
expect(assert_7.localizedPath).toBe('tab.localizedArray.<locale>.text')
107131
})
132+
133+
it('gets field nested within block', () => {
134+
const fieldInBlock = getFieldByPath({ fields, path: 'blocks.block2.text2' })
135+
expect(fieldInBlock?.field).toBeDefined()
136+
137+
const sourceField = (fields[4] as any).blocks?.[1].flattenedFields?.[0]
138+
expect(sourceField).toBeDefined()
139+
expect(fieldInBlock?.field).toBe(sourceField)
140+
})
108141
})

packages/payload/src/utilities/getFieldByPath.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ import type { SanitizedConfig } from '../config/types.js'
22
import type { FlattenedField } from '../fields/config/types.js'
33

44
/**
5-
* Get the field from by its path.
6-
* Can accept nested paths, e.g: group.title, array.group.title
7-
* If there were any localized on the path, pathHasLocalized will be true and localizedPath will look like:
8-
* group.<locale>.title // group is localized here
5+
* Get the field by its schema path, e.g. group.title, array.group.title
6+
* If there were any localized on the path, `pathHasLocalized` will be true and `localizedPath` will look like:
7+
* `group.<locale>.title` // group is localized here
98
*/
109
export const getFieldByPath = ({
1110
config,
@@ -18,6 +17,9 @@ export const getFieldByPath = ({
1817
fields: FlattenedField[]
1918
includeRelationships?: boolean
2019
localizedPath?: string
20+
/**
21+
* The schema path, e.g. `array.group.title`
22+
*/
2123
path: string
2224
}): {
2325
field: FlattenedField
@@ -34,6 +36,7 @@ export const getFieldByPath = ({
3436

3537
while (segments.length > 0) {
3638
const segment = segments.shift()
39+
3740
localizedPath = `${localizedPath ? `${localizedPath}.` : ''}${segment}`
3841
const field = currentFields.find((each) => each.name === segment)
3942

@@ -68,19 +71,25 @@ export const getFieldByPath = ({
6871
}
6972
}
7073

71-
if ('blocks' in field) {
72-
for (const block of field.blocks) {
73-
const maybeField = getFieldByPath({
74+
if ('blocks' in field && segments.length > 0) {
75+
const blockSlug = segments[0]
76+
const block = field.blocks.find((b) => b.slug === blockSlug)
77+
78+
if (block) {
79+
segments.shift()
80+
localizedPath = `${localizedPath}.${blockSlug}`
81+
82+
if (segments.length === 0) {
83+
return null
84+
}
85+
86+
return getFieldByPath({
7487
config,
7588
fields: block.flattenedFields,
7689
includeRelationships,
7790
localizedPath,
78-
path: [...segments].join('.'),
91+
path: segments.join('.'),
7992
})
80-
81-
if (maybeField) {
82-
return maybeField
83-
}
8493
}
8594
}
8695

0 commit comments

Comments
 (0)