Skip to content

Commit

Permalink
Add async to Multiple DropDown
Browse files Browse the repository at this point in the history
  • Loading branch information
jducro committed Jul 27, 2018
1 parent 858603b commit ea45c12
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/Components/Choices/DropDown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
62 changes: 38 additions & 24 deletions src/Components/Choices/MultipleDropDown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) => (
Expand Down Expand Up @@ -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) => (
<div
className={classNames('dp-pc_checkbox')}
>
<span
className="dp-pc_checkbox__checkbox"
>
<input type="checkbox" checked={checked} readOnly />
<i />
<span className="dp-pc_checkbox__label">
{label}
</span>
</span>
</div>
);

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) => {
Expand All @@ -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 (
<AsyncSelect
value={this.state.value}
name={name}
isClearable={false}
onChange={value => 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}
/>
);
}
}

Expand Down
41 changes: 41 additions & 0 deletions tests/storybook/async_multiple_dropdown.jsx
Original file line number Diff line number Diff line change
@@ -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', () => (
<Formik
initialValues={{ filling: 'bacon' }}
onSubmit={action('submit')}
render={() => (
<Form>
<MultipleDropDown
name="filling"
dataSource={{ getOptions: filter => fakeAPI(filter, 300, options) }}
label="Filling"
multiple
/>
<Submit>Submit</Submit>
</Form>
)}
/>
));
1 change: 1 addition & 0 deletions tests/storybook/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import '../../src/style.css';

import './async_dropdown';
import './async_multiple_dropdown';
import './form';
import './checkboxes';
import './datepicker';
Expand Down

0 comments on commit ea45c12

Please sign in to comment.