Skip to content

Commit 2ec4d0c

Browse files
authored
feat: join field admin.defaultColumns (#9982)
Add the ability to specify which columns should appear in the relationship table of a join fields The new property is in the Join field `admin.defaultColumns` and can be set to an array of strings containing the field names in the desired order.
1 parent f5516b9 commit 2ec4d0c

File tree

6 files changed

+42
-16
lines changed

6 files changed

+42
-16
lines changed

docs/fields/join.mdx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,11 @@ _\* An asterisk denotes that a property is required._
145145

146146
You can control the user experience of the join field using the `admin` config properties. The following options are supported:
147147

148-
| Option | Description |
149-
|------------------------|----------------------------------------------------------------------------------------|
150-
| **`allowCreate`** | Set to `false` to remove the controls for making new related documents from this field. |
151-
| **`components.Label`** | Override the default Label of the Field Component. [More details](../admin/fields#label) |
148+
| Option | Description |
149+
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
150+
| **`defaultColumns`** | Array of field names that correspond to which columns to show in the relationship table. Default is the collection config. |
151+
| **`allowCreate`** | Set to `false` to remove the controls for making new related documents from this field. |
152+
| **`components.Label`** | Override the default Label of the Field Component. [More details](../admin/fields#label) |
152153

153154
## Join Field Data
154155

packages/payload/src/admin/functions/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export type ListQuery = {
4949

5050
export type BuildTableStateArgs = {
5151
collectionSlug: string
52-
columns?: any[] // TODO: type this (comes from ui pkg)
52+
columns?: { accessor: string; active: boolean }[]
5353
docs?: PaginatedDocs['docs']
5454
enableRowSelections?: boolean
5555
query?: ListQuery

packages/payload/src/fields/config/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1390,6 +1390,7 @@ export type JoinField = {
13901390
Error?: CustomComponent<JoinFieldErrorClientComponent | JoinFieldErrorServerComponent>
13911391
Label?: CustomComponent<JoinFieldLabelClientComponent | JoinFieldLabelServerComponent>
13921392
} & Admin['components']
1393+
defaultColumns?: string[]
13931394
disableBulkEdit?: never
13941395
readOnly?: never
13951396
} & Admin
@@ -1422,7 +1423,8 @@ export type JoinField = {
14221423
FieldGraphQLType
14231424

14241425
export type JoinFieldClient = {
1425-
admin?: AdminClient & Pick<JoinField['admin'], 'allowCreate' | 'disableBulkEdit' | 'readOnly'>
1426+
admin?: AdminClient &
1427+
Pick<JoinField['admin'], 'allowCreate' | 'defaultColumns' | 'disableBulkEdit' | 'readOnly'>
14261428
} & FieldBaseClient &
14271429
Pick<
14281430
JoinField,

packages/ui/src/elements/RelationshipTable/index.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,21 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
115115
newQuery.where = hoistQueryParamsToAnd(newQuery.where, filterOptions)
116116
}
117117

118+
// map columns from string[] to ColumnPreferences
119+
const defaultColumns = field.admin.defaultColumns
120+
? field.admin.defaultColumns.map((accessor) => ({
121+
accessor,
122+
active: true,
123+
}))
124+
: undefined
125+
118126
const {
119127
data: newData,
120128
state: newColumnState,
121129
Table: NewTable,
122130
} = await getTableState({
123131
collectionSlug: relationTo,
132+
columns: defaultColumns,
124133
docs,
125134
enableRowSelections: false,
126135
query: newQuery,
@@ -134,11 +143,12 @@ export const RelationshipTable: React.FC<RelationshipTableComponentProps> = (pro
134143
setIsLoadingTable(false)
135144
},
136145
[
137-
query,
138146
field.defaultLimit,
139147
field.defaultSort,
148+
field.admin.defaultColumns,
140149
collectionConfig.admin.pagination.defaultLimit,
141150
collectionConfig.defaultSort,
151+
query,
142152
filterOptions,
143153
getTableState,
144154
relationTo,

test/joins/collections/Categories.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ export const Categories: CollectionConfig = {
9191
type: 'join',
9292
collection: postsSlug,
9393
on: 'group.category',
94+
admin: {
95+
defaultColumns: ['id', 'createdAt', 'title'],
96+
},
9497
},
9598
{
9699
name: 'camelCasePosts',

test/joins/e2e.spec.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -218,16 +218,28 @@ test.describe('Join Field', () => {
218218
const titleAscButton = titleColumn.locator('button.sort-column__asc')
219219
await expect(titleAscButton).toBeVisible()
220220
await titleAscButton.click()
221-
await expect(joinField.locator('tbody tr:first-child td:nth-child(2)')).toHaveText(
222-
'Test Post 1',
223-
)
221+
await expect(joinField.locator('tbody .row-1')).toContainText('Test Post 1')
224222

225223
const titleDescButton = titleColumn.locator('button.sort-column__desc')
226224
await expect(titleDescButton).toBeVisible()
227225
await titleDescButton.click()
228-
await expect(joinField.locator('tbody tr:first-child td:nth-child(2)')).toHaveText(
229-
'Test Post 3',
230-
)
226+
await expect(joinField.locator('tbody .row-1')).toContainText('Test Post 3')
227+
})
228+
229+
test('should display relationship table with columns from admin.defaultColumns', async () => {
230+
await page.goto(categoriesURL.edit(categoryID))
231+
const joinField = page.locator('#field-group__relatedPosts.field-type.join')
232+
const thead = joinField.locator('.relationship-table thead')
233+
await expect(thead).toContainText('ID')
234+
await expect(thead).toContainText('Created At')
235+
await expect(thead).toContainText('Title')
236+
const innerText = await thead.innerText()
237+
238+
// expect the order of columns to be 'ID', 'Created At', 'Title'
239+
// eslint-disable-next-line payload/no-flaky-assertions
240+
expect(innerText.indexOf('ID')).toBeLessThan(innerText.indexOf('Created At'))
241+
// eslint-disable-next-line payload/no-flaky-assertions
242+
expect(innerText.indexOf('Created At')).toBeLessThan(innerText.indexOf('Title'))
231243
})
232244

233245
test('should update relationship table when new document is created', async () => {
@@ -276,9 +288,7 @@ test.describe('Join Field', () => {
276288
await titleField.fill('Test Post 1 Updated')
277289
await drawer.locator('button[id="action-save"]').click()
278290
await expect(drawer).toBeHidden()
279-
await expect(joinField.locator('tbody tr:first-child td:nth-child(2)')).toHaveText(
280-
'Test Post 1 Updated',
281-
)
291+
await expect(joinField.locator('tbody .row-1')).toContainText('Test Post 1 Updated')
282292
})
283293

284294
test('should render empty relationship table when creating new document', async () => {

0 commit comments

Comments
 (0)