Событие необходимо добавить в индивидуальную опцию, для реализации множественного выбора требуется довольно много строк. Вот несколько фрагментов, которые могут вас заинтересовать. Как видите, я не использую сторонние элементы управления.
<div className="_action">
<span
role="button"
aria-pressed="false"
tabIndex={0}
onClick={() => { onClear() }}
>
Clear Selection
</span>
</div>
{options.map(option => (
<div
role="presentation"
className="_item"
key={option.value}
onClick={() => { onSelect(option.value) }}
>
<Checkbox value={isChecked(option, value)} />
<span className="_label">{option.label}</span>
</div>
))}
onSelect
и onClear
могут быть предоставлены из родительского / собственного компонента,
const onSelect = useCallback(v => {
const e = {
target: {
name,
value: toggleValueInOptions(value, v, options)
}
}
onChange(e)
}, [name, value, options, onChange])
const onClear = useCallback(() => {
const e = { target: { name, value: [] } }
onChange(e)
}, [name, onChange])
и служебная функция toggleValueiInOptions
const toggleValueInOptions = (value, key, options) => {
if (!value) return []
const values = value.slice()
const index = values.indexOf(key)
if (index >= 0) {
values.splice(index, 1)
} else {
values.push(key)
}
if (!options) return values
return options.reduce((acc, option) => {
if (values.includes(option.value)) {
acc.push(option.value)
}
return acc
}, [])
}
export default toggleValueInOptions
==============
Для справки, это полный код для родительского MultiSelect
.
import React, { useState, useCallback, useRef } from 'react'
import PropTypes from 'prop-types'
import { useClickOutside } from '../../utils'
import InputBase from '../InputBase'
import Pills from './Pills'
import MultiSelection from './MultiSelection'
import MultiSelectStyle from './MultiSelectStyle'
import SelectIcon from './SelectIcon'
import { optionsType, valuesType } from './optionsType'
import toggleValueInOptions from './toggleValueInOptions'
import valueToItems from './valueToItems'
import SelectionSummary from './SelectionSummary'
/**
* @memberof MultiSelect
* @param {Object} _ Props
* @param {elementType} _.Style Style component
* @param {string} _.name Input name
* @param {valueType[]} _.value Input value of array
* @param {func} _.onChange Value change event
* @param {optionsType[]} _.options Options array
* @param {elementType} _.Selection=MultiSelection Component for dropdown selection
* @param {bool} _.disabled=false Input disabled flag
* @param {bool} _.width=auto Input width
* @param {string} _.placeholder Input placeholder
* @param {elementType} _.DropdownIcon=DropdownIcon Compoent for dropdown icon component
* @param {number} _.pillVisibleMax Max pill displayed
* @param {elementType} _.Summary=SelectionSummary Component for dropdown summary
*/
const MultiSelect = ({
Style, name, value, options, onChange,
Selection, disabled, width, placeholder,
DropdownIcon, pillVisibleMax, Summary,
...props
}) => {
const [focus, setFocus] = useState(false)
const onExpand = useCallback(() => {
if (!disabled) setFocus(true)
}, [disabled])
const onCollapse = useCallback(() => { setFocus(false) }, [])
const ref = useRef()
useClickOutside({ ref, handler: () => { onCollapse() } })
const onSelect = useCallback(v => {
const e = {
target: {
name,
value: toggleValueInOptions(value, v, options)
}
}
onChange(e)
}, [name, value, options, onChange])
const onClear = useCallback(() => {
const e = { target: { name, value: [] } }
onChange(e)
}, [name, onChange])
const after = <DropdownIcon focus={focus} onExpand={onExpand} onCollapse={onCollapse} />
const phText = value.length ? '' : placeholder
const vText = (value.length > pillVisibleMax) ? `${value.length} Selected` : ''
return (
<Style ref={ref}>
<InputBase
value={vText}
placeholder={phText}
disabled={disabled}
readOnly
after={after}
onFocus={onExpand}
width={width}
{...props}
/>
{!vText && (
<Pills
items={valueToItems(value, options)}
onSelect={onSelect}
disabled={disabled}
/>
)}
{focus && (
<Selection
value={value}
options={options}
onSelect={onSelect}
onClear={onClear}
Summary={Summary}
/>
)}
</Style>
)
}
MultiSelect.propTypes = {
Style: PropTypes.elementType,
name: PropTypes.string,
value: valuesType,
options: optionsType,
onChange: PropTypes.func,
Selection: PropTypes.elementType,
disabled: PropTypes.bool,
width: PropTypes.string,
placeholder: PropTypes.string,
DropdownIcon: PropTypes.elementType,
pillVisibleMax: PropTypes.number,
Summary: PropTypes.elementType
}
MultiSelect.defaultProps = {
Style: MultiSelectStyle,
name: '',
value: [],
options: [],
onChange: () => { },
Selection: MultiSelection,
disabled: false,
width: '',
placeholder: '',
DropdownIcon: SelectIcon,
pillVisibleMax: 99,
Summary: SelectionSummary
}
export default MultiSelect