1
1
import React , { useState , useEffect } from 'react' ;
2
- import PropTypes from 'prop-types' ;
2
+ import PropTypes , { bool } from 'prop-types' ;
3
3
import { useFieldApi } from '@data-driven-forms/react-form-renderer' ;
4
4
5
5
import DataDrivenSelect from '@data-driven-forms/common/src/select' ;
6
- import useIsMounted from '@data-driven-forms/common/src/hooks/use-is-mounted' ;
7
6
import fnToString from '@data-driven-forms/common/src/utils/fn-to-string' ;
8
7
9
8
import { Select as CarbonSelect , MultiSelect , SelectItem } from 'carbon-components-react' ;
10
9
import prepareProps from '../common/prepare-props' ;
11
10
12
- const ClearedMultiSelectFilterable = ( props ) => {
13
- return 'multi.searchable' ;
11
+ const ClearedMultiSelectFilterable = ( {
12
+ invalidText,
13
+ hideSelectedOptions,
14
+ noOptionsMessage,
15
+ onInputChange,
16
+ options,
17
+ isFetching,
18
+ invalid,
19
+ isMulti,
20
+ classNamePrefix,
21
+ closeMenuOnSelect,
22
+ onChange,
23
+ originalOnChange,
24
+ carbonLabel,
25
+ placeholder,
26
+ isDisabled,
27
+ ...rest
28
+ } ) => (
29
+ < MultiSelect . Filterable
30
+ disabled = { isDisabled }
31
+ { ...rest }
32
+ placeholder = { carbonLabel || placeholder }
33
+ onChange = { originalOnChange }
34
+ titleText = { rest . labelText }
35
+ id = { rest . name }
36
+ invalid = { Boolean ( invalidText ) }
37
+ invalidText = { invalidText }
38
+ items = { options }
39
+ initialSelectedItems = { Array . isArray ( rest . value ) ? rest . value : [ ] }
40
+ />
41
+ ) ;
42
+
43
+ ClearedMultiSelectFilterable . propTypes = {
44
+ invalidText : PropTypes . node ,
45
+ hideSelectedOptions : PropTypes . any ,
46
+ noOptionsMessage : PropTypes . any ,
47
+ onInputChange : PropTypes . func ,
48
+ options : PropTypes . array ,
49
+ isFetching : PropTypes . bool ,
50
+ invalid : PropTypes . oneOfType ( [ PropTypes . bool , PropTypes . node ] ) ,
51
+ isMulti : PropTypes . bool ,
52
+ classNamePrefix : PropTypes . any ,
53
+ closeMenuOnSelect : PropTypes . any ,
54
+ onChange : PropTypes . func ,
55
+ originalOnChange : PropTypes . func ,
56
+ carbonLabel : PropTypes . node ,
57
+ placeholder : PropTypes . node ,
58
+ isDisabled : PropTypes . bool
14
59
} ;
15
60
16
- const ClearedMultiSelect = ( props ) => {
17
- return 'multi' ;
61
+ const ClearedMultiSelect = ( {
62
+ invalidText,
63
+ hideSelectedOptions,
64
+ noOptionsMessage,
65
+ onInputChange,
66
+ options,
67
+ isFetching,
68
+ invalid,
69
+ isMulti,
70
+ classNamePrefix,
71
+ closeMenuOnSelect,
72
+ onChange,
73
+ originalOnChange,
74
+ carbonLabel,
75
+ placeholder,
76
+ isDisabled,
77
+ ...rest
78
+ } ) => (
79
+ < MultiSelect
80
+ disabled = { isDisabled }
81
+ { ...rest }
82
+ label = { carbonLabel || placeholder }
83
+ onChange = { originalOnChange }
84
+ titleText = { rest . labelText }
85
+ id = { rest . name }
86
+ invalid = { Boolean ( invalidText ) }
87
+ invalidText = { invalidText }
88
+ items = { options }
89
+ initialSelectedItems = { Array . isArray ( rest . value ) ? rest . value : [ ] }
90
+ />
91
+ ) ;
92
+
93
+ ClearedMultiSelect . propTypes = {
94
+ invalidText : PropTypes . node ,
95
+ hideSelectedOptions : PropTypes . any ,
96
+ noOptionsMessage : PropTypes . any ,
97
+ onInputChange : PropTypes . func ,
98
+ options : PropTypes . array ,
99
+ isFetching : PropTypes . bool ,
100
+ invalid : PropTypes . oneOfType ( [ PropTypes . bool , PropTypes . node ] ) ,
101
+ isMulti : PropTypes . bool ,
102
+ classNamePrefix : PropTypes . any ,
103
+ closeMenuOnSelect : PropTypes . any ,
104
+ onChange : PropTypes . func ,
105
+ originalOnChange : PropTypes . func ,
106
+ carbonLabel : PropTypes . node ,
107
+ placeholder : PropTypes . node ,
108
+ isDisabled : PropTypes . bool
18
109
} ;
19
110
20
- const ClearedSelect = ( { invalidText, hideSelectedOptions, noOptionsMessage, onInputChange, options, isFetching, invalid, ...rest } ) => {
21
- return (
22
- < CarbonSelect { ...rest } if = { rest . name } invalid = { Boolean ( invalidText ) } invalidText = { invalidText } >
23
- { options . map ( ( option , index ) => (
24
- < SelectItem key = { option . value || index } text = { option . label } { ...option } />
25
- ) ) }
26
- </ CarbonSelect >
27
- ) ;
111
+ const ClearedSelect = ( {
112
+ isSearchable,
113
+ isClearable,
114
+ isDisabled,
115
+ isMulti,
116
+ invalidText,
117
+ hideSelectedOptions,
118
+ noOptionsMessage,
119
+ onInputChange,
120
+ options,
121
+ isFetching,
122
+ invalid,
123
+ classNamePrefix,
124
+ closeMenuOnSelect,
125
+ originalOnChange,
126
+ placeholder,
127
+ ...rest
128
+ } ) => (
129
+ < CarbonSelect disabled = { isFetching } { ...rest } id = { rest . name } invalid = { Boolean ( invalidText ) } invalidText = { invalidText } >
130
+ { isFetching && < SelectItem text = { placeholder } value = { '' } /> }
131
+ { options . map ( ( option , index ) => (
132
+ < SelectItem key = { option . value || index } text = { option . label } { ...option } />
133
+ ) ) }
134
+ </ CarbonSelect >
135
+ ) ;
136
+
137
+ ClearedSelect . propTypes = {
138
+ invalidText : PropTypes . node ,
139
+ hideSelectedOptions : PropTypes . any ,
140
+ noOptionsMessage : PropTypes . any ,
141
+ onInputChange : PropTypes . func ,
142
+ options : PropTypes . array ,
143
+ isFetching : PropTypes . bool ,
144
+ invalid : PropTypes . oneOfType ( [ PropTypes . bool , PropTypes . node ] ) ,
145
+ isMulti : PropTypes . bool ,
146
+ classNamePrefix : PropTypes . any ,
147
+ closeMenuOnSelect : PropTypes . any ,
148
+ onChange : PropTypes . func ,
149
+ originalOnChange : PropTypes . func ,
150
+ carbonLabel : PropTypes . node ,
151
+ placeholder : PropTypes . node ,
152
+ isDisabled : PropTypes . bool ,
153
+ isSearchable : bool ,
154
+ isClearable : bool
28
155
} ;
29
156
30
157
const Select = ( props ) => {
31
158
const { isMulti, isSearchable, loadOptions, input, meta, ...rest } = useFieldApi ( prepareProps ( props ) ) ;
32
159
33
- const [ isFetching , setFetching ] = useState ( loadOptions ? true : false ) ;
34
- const [ options , setOptions ] = useState ( props . options || [ ] ) ;
35
- const isMounted = useIsMounted ( ) ;
36
-
37
- // common select controls the string of loadOptions and if the string changed, then it reloads options
38
- // however we are enhancing the loadOptions here so the string is always the same
39
- // by increasing this counter, we can enforce the update
40
160
const [ loadOptionsChangeCounter , setCounter ] = useState ( 0 ) ;
41
161
42
162
const loadOptionsStr = fnToString ( loadOptions ) ;
@@ -46,36 +166,28 @@ const Select = (props) => {
46
166
// eslint-disable-next-line react-hooks/exhaustive-deps
47
167
} , [ loadOptionsStr ] ) ;
48
168
49
- const loadOptionsEnhanced = loadOptions
50
- ? ( value ) => {
51
- if ( isMounted . current ) {
52
- setFetching ( true ) ;
53
- }
54
-
55
- return loadOptions ( value ) . then ( ( data ) => {
56
- if ( isMounted . current ) {
57
- setOptions ( [ ...options , ...data . filter ( ( { value } ) => ! options . find ( ( option ) => option . value === value ) ) ] ) ;
58
- setFetching ( false ) ;
59
- }
60
-
61
- return data ;
62
- } ) ;
63
- }
64
- : undefined ;
65
-
66
169
const Component = isMulti && isSearchable ? ClearedMultiSelectFilterable : isMulti ? ClearedMultiSelect : ClearedSelect ;
67
170
68
171
const invalidText = ( meta . touched && meta . error ) || '' ;
69
172
173
+ const specialOnChange = ( { selectedItems } ) => {
174
+ if ( rest . simpleValue ) {
175
+ return input . onChange ( selectedItems . map ( ( { value } ) => value ) ) ;
176
+ } else {
177
+ return input . onChange ( selectedItems ) ;
178
+ }
179
+ } ;
180
+
70
181
return (
71
182
< DataDrivenSelect
72
183
SelectComponent = { Component }
184
+ simpleValue = { false }
73
185
{ ...rest }
74
186
{ ...input }
187
+ loadOptions = { loadOptions }
75
188
invalidText = { invalidText }
76
189
loadOptionsChangeCounter = { loadOptionsChangeCounter }
77
- loadOptions = { loadOptionsEnhanced }
78
- simpleValue = { false }
190
+ originalOnChange = { specialOnChange }
79
191
/>
80
192
) ;
81
193
} ;
@@ -90,4 +202,8 @@ Select.propTypes = {
90
202
)
91
203
} ;
92
204
205
+ Select . defaultProps = {
206
+ loadingMessage : 'Loading...'
207
+ } ;
208
+
93
209
export default Select ;
0 commit comments