[英]Multiselect in a dropdown list in React
I am trying to be able to multi select different values from a dropdown I created.我试图能够从我创建的下拉列表中多 select 不同的值。 So the following code is actually showing the names of the people but I would like to be able to select more than one.所以下面的代码实际上是显示人的名字但我希望能够 select 不止一个。
<Form.Group controlId="exampleForm.ControlSelect4">
<Form.Label> Names </Form.Label>
<Form.Control as="select" value={this.state.selectedNames}
onChange={this.updateTable}>
{this.state.names.map((name) => <option key={name.value} value={name.value}> {name.display } </option>)}
</Form.Control>
</Form.Group>
It is similar to setting a single value but instead, the value is an array instead of a string or a number.它类似于设置单个值,但取而代之的是,该值是一个数组,而不是字符串或数字。
First, you have to change what the value and onChange function are doing.首先,您必须更改 value 和 onChange function 正在做什么。 For the value, set the default state as an array.对于该值,将默认 state 设置为数组。 For the onChange
, we are going to set it where whenever the item is checked, it sets a new state so like this:对于onChange
,我们将在每次检查项目时将其设置为新的 state ,如下所示:
javascript javascript
state = {
selectedNames:[]
}
onChange = (e) => {
e.preventDefault()
this.setState(prevState => ({selectedNames: [...prevState.selectedNames, e.target.value]})
}
Hopefully, this helps!希望这会有所帮助!
The event needs to be added to individual option, multi select takes quite a bit of lines to implement.该事件需要添加到单个选项中,多 select 需要相当多的行来实现。 Here's some snippet just for the sections you might care.这是您可能关心的部分的一些片段。 I'm not using any third party controls as you can see.如您所见,我没有使用任何第三方控件。
<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>
))}
The onSelect
and onClear
might be provided from parent/self component, onSelect
和onClear
可能由 parent/self 组件提供,
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])
and a utility function toggleValueiInOptions
和一个实用程序 function 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
For your reference, this is the complete code for the parent MultiSelect
.供您参考,这是父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
(I'm assuming you are using react-bootstrap
) (我假设您正在使用react-bootstrap
)
You will need to pass another prop to Form.Control
to specify that you would like your select to allow multiple selections.您需要将另一个道具传递给Form.Control
以指定您希望 select 允许多项选择。 You can do this either as multiple={true}
, or as the shorthand multiple
(both are equivalent).您可以将其作为multiple={true}
或作为速记multiple
(两者是等效的)来执行此操作。
This example in their docs uses a multiselect, that might be helpful.他们文档中的这个示例使用了多选,这可能会有所帮助。
I put together this sandbox which might illustrate how to use it.我把这个沙盒放在一起,可以说明如何使用它。
Handling state with react can be hard.用反应处理 state 可能很难。 Forms are notoriously challenging because they involve a lot of internal state. Forms 是出了名的具有挑战性,因为它们涉及很多内部 state。
onChange
event is not trigged.当只有一个选择并且您尝试取消选择它时,不会触发onChange
事件。 I'm not sure why that's happening here我不确定为什么会在这里发生
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.