Skip to content
This repository was archived by the owner on May 17, 2023. It is now read-only.

Commit 3330cf7

Browse files
author
Franco Correa
authored
Support getOptionValue in select (#1555)
1 parent 44461dc commit 3330cf7

File tree

2 files changed

+70
-12
lines changed

2 files changed

+70
-12
lines changed

core/components/atoms/select/select.js

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ const selectOpacity = {
1616
disabled: 0.5
1717
}
1818

19+
const defaultGetOptionValue = option => option.value
20+
1921
const selectTheme = {
2022
...defaultTheme,
2123
colors: {
@@ -39,14 +41,14 @@ const cosmosToReactSelect = {
3941
options: items ? cosmosToReactSelect.options(items) : undefined,
4042
...otherProperties
4143
})),
42-
value: (valueProp, options) => {
44+
value: (valueProp, options, getOptionValue = defaultGetOptionValue) => {
4345
if (valueProp === null || typeof valueProp === 'undefined') return null
4446

4547
if (valueProp.constructor.name === 'Array') {
46-
return valueProp.map(item => cosmosToReactSelect.value(item, options))
48+
return valueProp.map(item => cosmosToReactSelect.value(item, options, getOptionValue))
4749
}
4850

49-
const matchValue = option => option.value === valueProp
51+
const matchValue = option => getOptionValue(option) === valueProp
5052

5153
let valueFound = null
5254

@@ -117,15 +119,13 @@ const cosmosDownIndicator = ({ innerProps }) => (
117119

118120
const cosmosLoadingIndicator = () => <Select.Spinner />
119121

120-
const oneOrMore = options => {
122+
const oneOrMore = (options, getOptionValue = defaultGetOptionValue) => {
121123
if (options === null) return null
122124

123-
const transformation = option => option.value
124-
125125
if (options.constructor.name === 'Array') {
126-
return options.map(transformation)
126+
return options.map(getOptionValue)
127127
}
128-
return transformation(options)
128+
return getOptionValue(options)
129129
}
130130

131131
const componentOverrides = {
@@ -171,7 +171,15 @@ class Select extends React.Component {
171171
render() {
172172
const props = this.props
173173

174-
if (!(props.async || props.searchable || props.multiple || props.customOptionRenderer))
174+
if (
175+
!(
176+
props.async ||
177+
props.searchable ||
178+
props.multiple ||
179+
props.customOptionRenderer ||
180+
props.getOptionValue
181+
)
182+
)
175183
return <SimpleSelect {...props} />
176184

177185
/*
@@ -193,7 +201,9 @@ class Select extends React.Component {
193201
* If the Select is async we need to get the complete object value from the user,
194202
* while if it's a sync select, we can just get the value and match it from the options.
195203
*/
196-
const value = props.async ? props.value : cosmosToReactSelect.value(props.value, options)
204+
const value = props.async
205+
? props.value
206+
: cosmosToReactSelect.value(props.value, options, props.getOptionValue)
197207
const styles = cosmosToReactSelect.styles(props)
198208
const searchable = props.async || props.searchable
199209

@@ -207,7 +217,7 @@ class Select extends React.Component {
207217
const SelectProvider = props.async ? AsyncSelect : ReactSelect
208218

209219
const onChange = options => {
210-
const newValue = props.async ? options : oneOrMore(options)
220+
const newValue = props.async ? options : oneOrMore(options, props.getOptionValue)
211221
if (props.onChange) props.onChange({ target: { name: props.name, value: newValue } })
212222
}
213223

@@ -227,6 +237,7 @@ class Select extends React.Component {
227237
menuPortalTarget={document.body}
228238
menuIsOpen={props.defaultMenuOpen}
229239
defaultValue={props.defaultValue}
240+
getOptionValue={props.getOptionValue}
230241
placeholder={props.placeholder}
231242
options={options}
232243
loadOptions={props.loadOptions}
@@ -290,6 +301,8 @@ Select.propTypes = {
290301
customOptionRenderer: PropTypes.func,
291302
/** If you want an async select, you can pass a function which can return a Promise here */
292303
loadOptions: PropTypes.func,
304+
/** Lets you specify a different key from where the select should take the value from a selected option */
305+
getOptionValue: PropTypes.func,
293306
/** Used to specify a message for when there's no options */
294307
noOptionsMessage: PropTypes.oneOfType([PropTypes.func || PropTypes.string]),
295308
/** Used to provide default options for the select (as object) or tell the select to search with '' (as boolean) */

core/components/atoms/select/select.story.js

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class InteractiveSelect extends React.Component {
1818
}
1919

2020
onChange(event) {
21-
console.log('Changing to:', event.target.value)
2221
this.setState({ value: event.target.value })
2322
}
2423

@@ -79,6 +78,52 @@ storiesOf('Select', module).add('multiple tags', () => (
7978
</ExampleForSelect>
8079
))
8180

81+
storiesOf('Select', module).add('simple with custom getOptionValue', () => (
82+
<ExampleForSelect title="Select: custom getOptionValue">
83+
<InteractiveSelect>
84+
{(value, onChange) => (
85+
<div>
86+
<Select
87+
options={[
88+
{ text: 'One', myCustomValue: 1 },
89+
{ text: 'Two', myCustomValue: 2 },
90+
{ text: 'Three', myCustomValue: 3 }
91+
]}
92+
value={value}
93+
onChange={onChange}
94+
getOptionValue={option => option.myCustomValue}
95+
/>
96+
<p>Selected value: {value}</p>
97+
</div>
98+
)}
99+
</InteractiveSelect>
100+
</ExampleForSelect>
101+
))
102+
103+
storiesOf('Select', module).add('multiple with custom getOptionValue', () => (
104+
<ExampleForSelect title="Select: custom getOptionValue">
105+
<InteractiveSelect>
106+
{(value, onChange) => (
107+
<div>
108+
<Select
109+
multiple
110+
searchable
111+
options={[
112+
{ text: 'One', myCustomValue: 1 },
113+
{ text: 'Two', myCustomValue: 2 },
114+
{ text: 'Three', myCustomValue: 3 }
115+
]}
116+
value={value}
117+
onChange={onChange}
118+
getOptionValue={option => option.myCustomValue}
119+
/>
120+
<p>Selected value: {(value || []).join(',')}</p>
121+
</div>
122+
)}
123+
</InteractiveSelect>
124+
</ExampleForSelect>
125+
))
126+
82127
storiesOf('Select', module).add('multiple tags: open', () => (
83128
<ExampleForSelect title="Select: stressed multiple tags">
84129
<Select

0 commit comments

Comments
 (0)