From ea45c12cb74a60f75018bb6382ee305f721e3924 Mon Sep 17 00:00:00 2001 From: Julien Ducro Date: Fri, 27 Jul 2018 10:47:14 +0200 Subject: [PATCH] Add async to Multiple DropDown --- src/Components/Choices/DropDown.jsx | 2 +- src/Components/Choices/MultipleDropDown.jsx | 62 +++++++++++++-------- tests/storybook/async_multiple_dropdown.jsx | 41 ++++++++++++++ tests/storybook/index.js | 1 + 4 files changed, 81 insertions(+), 25 deletions(-) create mode 100644 tests/storybook/async_multiple_dropdown.jsx diff --git a/src/Components/Choices/DropDown.jsx b/src/Components/Choices/DropDown.jsx index 5a22315c..1bfe8118 100644 --- a/src/Components/Choices/DropDown.jsx +++ b/src/Components/Choices/DropDown.jsx @@ -68,7 +68,7 @@ class DropDown extends Field { value={this.state.value} name={name} isClearable={isClearable} - onChange={(value, action) => this.handleChange(form, value, action)} + onChange={value => this.handleChange(form, value)} onBlur={() => form.setFieldTouched(name, true)} defaultOptions cacheOptions diff --git a/src/Components/Choices/MultipleDropDown.jsx b/src/Components/Choices/MultipleDropDown.jsx index 1c7acddf..56aa2de2 100644 --- a/src/Components/Choices/MultipleDropDown.jsx +++ b/src/Components/Choices/MultipleDropDown.jsx @@ -4,7 +4,7 @@ import classNames from 'classnames'; import { css } from 'emotion'; import { getIn } from 'formik'; import ReactSelect, { components } from 'react-select'; - +import AsyncSelect from 'react-select/lib/Async'; import Field from '../Field'; const SelectContainer = ({ children, ...props }) => ( @@ -59,33 +59,32 @@ const Option = (props) => { Option.propTypes = components.Option.propTypes; class MultipleDropDown extends Field { + constructor(props) { + super(props); + this.state = { + value: null + }; + } + handleChange = (form, value) => { const { name, handleChange } = this.props; + this.setState({ + value + }); const newValue = value ? value.map(e => e.value) : null; form.setFieldValue(name, newValue); handleChange(newValue); }; - renderCheckbox = (checked, label) => ( -
- - - - - {label} - - -
- ); - - renderOption = (option, form) => { - const { name } = this.props; - const checked = form.values[name].includes(option.value); - return this.renderCheckbox(checked, option.label); + loadOptions = (form, inputValue) => { + const { dataSource, name } = this.props; + return dataSource.getOptions(inputValue).then((options) => { + const value = options.find(o => o.value === getIn(form.values, name)); + this.setState({ + value + }); + return options; + }); }; renderField = (form) => { @@ -100,16 +99,31 @@ class MultipleDropDown extends Field { onBlur={() => form.setFieldTouched(name, true)} options={dataSource.getOptions} hideSelectedOptions={false} - menuIsOpen components={{ Option, SelectContainer }} - optionRenderer={option => this.renderOption(option, form)} classNamePrefix="react-select" isMulti {...props} /> ); } - return null; + + return ( + this.handleChange(form, value)} + onBlur={() => form.setFieldTouched(name, true)} + hideSelectedOptions={false} + components={{ Option, SelectContainer }} + defaultOptions + cacheOptions + loadOptions={inputValue => this.loadOptions(form, inputValue)} + classNamePrefix="react-select" + isMulti + {...props} + /> + ); } } diff --git a/tests/storybook/async_multiple_dropdown.jsx b/tests/storybook/async_multiple_dropdown.jsx new file mode 100644 index 00000000..8d02dbb3 --- /dev/null +++ b/tests/storybook/async_multiple_dropdown.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; +import { Formik } from 'formik'; +import { Form, MultipleDropDown, Submit } from '../../src/Components'; + +const options = [ + { value: 'bacon', label: 'Bacon' }, + { value: 'cheese', label: 'Cheese' }, + { value: 'jalapenos', label: 'JalapeƱos' }, + { value: 'mushrooms', label: 'Mushrooms' }, + { value: 'onions', label: 'Onions' }, + { value: 'pickles', label: 'Pickles' }, +]; + +const fakeAPI = (filter, delay, value) => new Promise((resolve) => { + setTimeout(() => { + const regexp = new RegExp(filter.toLowerCase()); + const result = value.filter(o => o.label.toLowerCase().match(regexp) || filter === ''); + resolve(result); + }, delay); +}); + +storiesOf('Choices', module) + .add('Async MultipleDropdown', () => ( + ( +
+ fakeAPI(filter, 300, options) }} + label="Filling" + multiple + /> + Submit + + )} + /> + )); diff --git a/tests/storybook/index.js b/tests/storybook/index.js index 8402eefc..de396aff 100644 --- a/tests/storybook/index.js +++ b/tests/storybook/index.js @@ -1,6 +1,7 @@ import '../../src/style.css'; import './async_dropdown'; +import './async_multiple_dropdown'; import './form'; import './checkboxes'; import './datepicker';