File tree Expand file tree Collapse file tree 6 files changed +81
-17
lines changed
packages/payload/src/admin/fields Expand file tree Collapse file tree 6 files changed +81
-17
lines changed Original file line number Diff line number Diff line change @@ -25,7 +25,7 @@ type SelectFieldBaseClientProps = {
25
25
readonly onChange ?: ( e : string | string [ ] ) => void
26
26
readonly path : string
27
27
readonly validate ?: SelectFieldValidation
28
- readonly value ?: string
28
+ readonly value ?: string | string [ ]
29
29
}
30
30
31
31
type SelectFieldBaseServerProps = Pick < FieldPaths , 'path' >
Original file line number Diff line number Diff line change
1
+ 'use client'
2
+
3
+ import type { Option , SelectFieldClientComponent } from 'payload'
4
+
5
+ import { SelectField , useField } from '@payloadcms/ui'
6
+ import React from 'react'
7
+
8
+ export const CustomMultiSelect : SelectFieldClientComponent = ( props ) => {
9
+ const { path } = props
10
+ const { setValue, value } = useField < string [ ] > ( { path } )
11
+ const [ options , setOptions ] = React . useState < Option [ ] > ( [ ] )
12
+
13
+ React . useEffect ( ( ) => {
14
+ const fetchOptions = ( ) => {
15
+ const fetched : Option [ ] = [
16
+ { label : 'Label 1' , value : 'value1' } ,
17
+ { label : 'Label 2' , value : 'value2' } ,
18
+ ]
19
+ setOptions ( fetched )
20
+ }
21
+ void fetchOptions ( )
22
+ } , [ ] )
23
+
24
+ const onChange = ( val : string | string [ ] ) => {
25
+ setValue ( Array . isArray ( val ) ? val : val ? [ val ] : [ ] )
26
+ }
27
+
28
+ return (
29
+ < SelectField
30
+ { ...props }
31
+ field = { {
32
+ ...props . field ,
33
+ name : path ,
34
+ hasMany : true ,
35
+ options,
36
+ } }
37
+ onChange = { onChange }
38
+ value = { value ?? [ ] }
39
+ />
40
+ )
41
+ }
Original file line number Diff line number Diff line change @@ -8,28 +8,21 @@ import React from 'react'
8
8
export const CustomSelect : SelectFieldClientComponent = ( props ) => {
9
9
const { path } = props
10
10
const { setValue, value } = useField < string > ( { path } )
11
- const [ options , setOptions ] = React . useState < { label : string ; value : string } [ ] > ( [ ] )
11
+ const [ options , setOptions ] = React . useState < Option [ ] > ( [ ] )
12
12
13
13
React . useEffect ( ( ) => {
14
14
const fetchOptions = ( ) => {
15
- const fetchedOptions = [
16
- {
17
- label : 'Label 1' ,
18
- value : 'value1' ,
19
- } ,
20
- {
21
- label : 'Label 2' ,
22
- value : 'value2' ,
23
- } ,
15
+ const fetchedOptions : Option [ ] = [
16
+ { label : 'Label 1' , value : 'value1' } ,
17
+ { label : 'Label 2' , value : 'value2' } ,
24
18
]
25
19
setOptions ( fetchedOptions )
26
20
}
27
21
void fetchOptions ( )
28
22
} , [ ] )
29
23
30
- const onChange = ( selected : Option | Option [ ] ) => {
31
- const options = Array . isArray ( selected ) ? selected : [ selected ]
32
- setValue ( options . map ( ( option ) => ( typeof option === 'string' ? option : option . value ) ) )
24
+ const onChange = ( val : string | string [ ] ) => {
25
+ setValue ( Array . isArray ( val ) ? ( val [ 0 ] ?? '' ) : val )
33
26
}
34
27
35
28
return (
@@ -38,12 +31,10 @@ export const CustomSelect: SelectFieldClientComponent = (props) => {
38
31
{ ...props }
39
32
field = { {
40
33
...props . field ,
41
- name : path ,
42
- hasMany : true ,
43
34
options,
44
35
} }
45
36
onChange = { onChange }
46
- value = { value }
37
+ value = { value ?? '' }
47
38
/>
48
39
</ div >
49
40
)
Original file line number Diff line number Diff line change @@ -82,6 +82,16 @@ export const CustomFields: CollectionConfig = {
82
82
} ,
83
83
} ,
84
84
} ,
85
+ {
86
+ name : 'customMultiSelectField' ,
87
+ type : 'text' ,
88
+ hasMany : true ,
89
+ admin : {
90
+ components : {
91
+ Field : '/collections/CustomFields/fields/Select/CustomMultiSelect.js#CustomMultiSelect' ,
92
+ } ,
93
+ } ,
94
+ } ,
85
95
{
86
96
name : 'relationshipFieldWithBeforeAfterInputs' ,
87
97
type : 'relationship' ,
Original file line number Diff line number Diff line change @@ -649,6 +649,26 @@ describe('Document View', () => {
649
649
await page . locator ( '#field-customSelectField .rs__control' ) . click ( )
650
650
await expect ( page . locator ( '#field-customSelectField .rs__option' ) ) . toHaveCount ( 2 )
651
651
} )
652
+
653
+ test ( 'should render custom multi select options' , async ( ) => {
654
+ await page . goto ( customFieldsURL . create )
655
+ await page . locator ( '#field-customMultiSelectField .rs__control' ) . click ( )
656
+ await expect ( page . locator ( '#field-customMultiSelectField .rs__option' ) ) . toHaveCount ( 2 )
657
+ } )
658
+
659
+ test ( 'should allow selecting multiple values in custom multi select' , async ( ) => {
660
+ await page . goto ( customFieldsURL . create )
661
+
662
+ const control = page . locator ( '#field-customMultiSelectField .rs__control' )
663
+
664
+ await control . click ( )
665
+ await page . locator ( '.rs__option' , { hasText : 'Label 1' } ) . click ( )
666
+ await expect ( page . locator ( '#field-customMultiSelectField .rs__multi-value' ) ) . toHaveCount ( 1 )
667
+
668
+ await control . click ( )
669
+ await page . locator ( '.rs__option' , { hasText : 'Label 2' } ) . click ( )
670
+ await expect ( page . locator ( '#field-customMultiSelectField .rs__multi-value' ) ) . toHaveCount ( 2 )
671
+ } )
652
672
} )
653
673
} )
654
674
Original file line number Diff line number Diff line change @@ -384,6 +384,7 @@ export interface CustomField {
384
384
descriptionAsComponent ?: string | null ;
385
385
customSelectField ?: string | null ;
386
386
customSelectInput ?: string | null ;
387
+ customMultiSelectField ?: string [ ] | null ;
387
388
relationshipFieldWithBeforeAfterInputs ?: ( string | null ) | Post ;
388
389
arrayFieldWithBeforeAfterInputs ?:
389
390
| {
@@ -927,6 +928,7 @@ export interface CustomFieldsSelect<T extends boolean = true> {
927
928
descriptionAsComponent ?: T ;
928
929
customSelectField ?: T ;
929
930
customSelectInput ?: T ;
931
+ customMultiSelectField ?: T ;
930
932
relationshipFieldWithBeforeAfterInputs ?: T ;
931
933
arrayFieldWithBeforeAfterInputs ?:
932
934
| T
You can’t perform that action at this time.
0 commit comments