Skip to content

Commit

Permalink
fix(Select): scalar value instead of selected option
Browse files Browse the repository at this point in the history
  • Loading branch information
zouxuoz committed Mar 15, 2019
1 parent 1aec8a1 commit eecbc66
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 75 deletions.
94 changes: 59 additions & 35 deletions src/components/Select/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { PALETTE, Z_INDEX } from '../../theme';

type SelectProps = {|
options: Array<{ label: mixed, value: string }>,
onChange: (selectedValue: mixed, event?: SyntheticInputEvent<HTMLInputElement>) => void,
onChange: (value: mixed, event?: SyntheticInputEvent<HTMLInputElement>) => void,
placeholder?: string,
value?: Object | Object[],
value?: any | any[],
loading?: boolean,
disabled?: boolean,
multiple?: boolean,
Expand All @@ -19,6 +19,7 @@ type SelectProps = {|
zIndex?: string | number,
valueComponent?: React$Node,
components?: Object,
className?: string,
|};

const customStyles = ({ hasError, zIndex = Z_INDEX.DROPDOWN }) => ({
Expand Down Expand Up @@ -77,40 +78,63 @@ const customStyles = ({ hasError, zIndex = Z_INDEX.DROPDOWN }) => ({
}),
});

const Select = ({
value,
loading,
clearable,
disabled,
multiple,
options,
onChange,
placeholder,
valueComponent,
components,
...props
}: SelectProps) => {
return (
<SelectTag { ...props } aria-busy={ String(loading || false) }>
<ReactSelect
isClearable={ clearable }
isDisabled={ disabled }
isLoading={ loading }
isMulti={ multiple }
menuPlacement="auto"
menuPortalTarget={ document.body }
onChange={ onChange }
options={ options }
placeholder={ placeholder }
valueComponent={ valueComponent }
styles={ customStyles(props) }
value={ value }
components={ components }
/>
</SelectTag>
);
};
class Select extends React.Component<SelectProps> {
onChange = (option: Object) => {
let value = null;

if (Array.isArray(option)) {
value = option.map(({ value }) => value);
} else if (option) {
({ value } = option);
}

this.props.onChange(value);
};

render() {
const {
value,
loading,
clearable,
disabled,
multiple,
options,
placeholder,
valueComponent,
components,
onChange,
...rest
} = this.props;

const selectValue = (
Array.isArray(value)
? options.filter((option) => value.indexOf(option.value) !== -1)
: options.find((option) => option.value === value)
) || null;

return (
<SelectTag { ...rest } aria-busy={ String(loading || false) }>
<ReactSelect
isClearable={ clearable }
isDisabled={ disabled }
isLoading={ loading }
isMulti={ multiple }
menuPlacement="auto"
menuPortalTarget={ document.body }
onChange={ this.onChange }
options={ options }
placeholder={ placeholder }
valueComponent={ valueComponent }
styles={ customStyles(rest) }
value={ selectValue }
components={ components }
/>
</SelectTag>
);
}
}

// $FlowFixMe
Select.components = components;

export { Select };
Expand Down
8 changes: 4 additions & 4 deletions src/components/Select/Select.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ export default (asStory) => {
<StateContainer value={ null }>
<Select name="name" placeholder="Select an option" options={ OPTIONS } />
</StateContainer>
<StateContainer value={ OPTIONS[1] }>
<StateContainer value={ OPTIONS[1].value }>
<Select name="name" placeholder="Select an option" options={ OPTIONS } clearable />
</StateContainer>
<StateContainer value={ [OPTIONS[1], OPTIONS[2]] }>
<StateContainer value={ [OPTIONS[1].value, OPTIONS[2].value] }>
<Select name="name" placeholder="Select an option" options={ OPTIONS } multiple />
</StateContainer>
<StateContainer value={ [LONG_OPTIONS[1], LONG_OPTIONS[2]] }>
<StateContainer value={ [LONG_OPTIONS[1].value, LONG_OPTIONS[2].value] }>
<Select name="name" placeholder="Select an option" options={ LONG_OPTIONS } multiple />
</StateContainer>
<StateContainer value={ [OPTIONS[1], OPTIONS[2]] }>
<StateContainer value={ [OPTIONS[1].value, OPTIONS[2].value] }>
<Select
name="name"
placeholder="Select an option"
Expand Down
14 changes: 9 additions & 5 deletions src/components/Select/Select.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,46 @@ import { Select } from './';

describe('<Select />', () => {
it('should pass props to ReactSelect', () => {
const onChange = jest.fn();
const options = [{ label: 'ovenlike', value: 'ovenlike' }];
const placeholder = 'Select an option';
const clearable = true;
const multiple = true;
const hasError = false;
const loading = false;
const disabled = true;
const components = {};

const wrapper = mount(
<Select
clearable={ clearable }
multiple={ multiple }
hasError={ hasError }
onChange={ onChange }
onChange={ jest.fn() }
placeholder={ placeholder }
options={ options }
value={ options[0] }
value={ options[0].value }
loading={ loading }
disabled={ disabled }
components={ components }
/>,
);

const { children, ...passedStyledProps } = wrapper.find(SelectTag).props();
const { styles, menuPortalTarget, ...passedSelectProps } = wrapper.find(ReactSelect).props();
const { styles, menuPortalTarget, onChange, valueComponent, ...passedSelectProps } = wrapper.find(ReactSelect).props();

expect(passedSelectProps).toEqual({
isClearable: clearable,
isMulti: multiple,
isDisabled: disabled,
placeholder,
onChange,
options,
value: options[0],
defaultInputValue: '',
defaultMenuIsOpen: false,
defaultValue: null,
menuPlacement: 'auto',
isLoading: loading,
components,
});

expect(passedStyledProps).toEqual({
Expand Down
22 changes: 2 additions & 20 deletions src/components/SelectField/SelectField.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,6 @@ type SelectFieldProps = {
};

class SelectField extends React.Component<SelectFieldProps> {
onChange = (selectedOption) => {
let value = null;

if (Array.isArray(selectedOption)) {
value = selectedOption.map(({ value }) => value);
} else if (selectedOption) {
({ value } = selectedOption);
}

this.props.input.onChange(value);
};

collectFormFieldProps() {
const { meta, input, stretch, label } = this.props;

Expand All @@ -45,22 +33,16 @@ class SelectField extends React.Component<SelectFieldProps> {

const hasError = formUtils.hasError(meta);

const value = (
Array.isArray(input.value)
? options.filter((option) => input.value.indexOf(option.value) !== -1)
: options.find((option) => option.value === input.value)
) || null;

return {
...this.props,
name: input.name,
value,
value: input.value,
hasError,
placeholder,
options,
stretch,
multiple,
onChange: this.onChange,
onChange: input.onChange,
};
}

Expand Down
19 changes: 8 additions & 11 deletions src/components/SelectField/SelectField.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('<SelectField />', () => {
const placeholder = 'Select an option';
const clearable = true;
const multiple = true;
const input = { name: 'input', onChange: jest.fn() };
const input = { name: 'input', onChange: jest.fn(), value: null };
const meta = { error: 'asdasd', touched: true };

const wrapper = shallow(
Expand Down Expand Up @@ -72,15 +72,12 @@ describe('<SelectField />', () => {
/>,
);

expect(wrapper.find(Select).props().value).toEqual({
label: 'serjeant',
value: 'serjeant',
});
expect(wrapper.find(Select).props().value).toEqual('serjeant');

wrapper.setProps({ input: { value: ['ovenlike', 'serjeant'] }});
expect(wrapper.find(Select).props().value).toEqual([
{ label: 'ovenlike', value: 'ovenlike' },
{ label: 'serjeant', value: 'serjeant' },
'ovenlike',
'serjeant',
]);
});

Expand All @@ -96,13 +93,13 @@ describe('<SelectField />', () => {
/>,
);

wrapper.find(Select).props().onChange(options[0]);
expect(onChange.mock.calls[0][0]).toBe(options[0].label);
wrapper.find(Select).props().onChange(options[0].value);
expect(onChange.mock.calls[0][0]).toBe(options[0].value);

wrapper.find(Select).props().onChange(options);
wrapper.find(Select).props().onChange(['ovenlike', 'serjeant']);
expect(onChange.mock.calls[1][0]).toEqual(['ovenlike', 'serjeant']);

wrapper.find(Select).props().onChange();
wrapper.find(Select).props().onChange(null);
expect(onChange.mock.calls[2][0]).toBeNull();
});
});

0 comments on commit eecbc66

Please sign in to comment.