I am using CreatableSelect component from react-select. Now users can select as many items as they want, but I want users to select no more than 5 items. How to limit max number of options that can be selected?
<CreatableSelect
classes={classes}
styles={selectStyles}
textFieldProps={{
label: "Tags"
}}
options={suggestions}
components={components}
value={this.state.multi}
onChange={this.handleChange("multi")}
placeholder=""
isMulti
/>
I recommend you to use a combination of custom component Menu
and isValidNewOption
like the following code:
// For this example the limite will be 5
const Menu = props => {
const optionSelectedLength = props.getValue().length || 0;
return (
<components.Menu {...props}>
{optionSelectedLength < 5 ? (
props.children
) : (
<div>Max limit achieved</div>
)}
</components.Menu>
);
};
function App() {
const isValidNewOption = (inputValue, selectValue) =>
inputValue.length > 0 && selectValue.length < 5;
return (
<div className="App">
<Creatable
components={{ Menu }}
isMulti
isValidNewOption={isValidNewOption}
options={options}
/>
</div>
);
}
Here a live example .
The idea is to prevent user to access the options after the limit X (5 in the example) and also to prevent the enter
keyboard event on create through isValidNewOption
prop.
<CreatableSelect
classes={classes}
styles={selectStyles}
options={this.state.multi.length > 4 ? this.state.multi : suggestions}
components={Components}
value={this.state.multi}
placeholder="Tags"
onChange={(values) => this.setState({ multi: values })}
isValidNewOption={isValidNewOption} //Look at Marked Answer
isMulti
/>
Main documentation on how to resolve this issue can be found here:
https://github.com/JedWatson/react-select/issues/1341
const MultiCreatable = ({ options, handleChange, handleCreate, value, maxOptions }) => {
return (
<CreatableSelect
isMulti
placeholder={placeholder}
onChange={handleChange}
options={value.length === maxOptions ? [] : options}
noOptionsMessage={() => {
return value.length === maxOptions ? 'You have reached the max options value' : 'No options available' ;
}}
onCreateOption={handleCreate}
value={value}
/>
)
}
For my case I used normal Select Component from react-select.
<Select
options={industries}
value={industry}
getOptionLabel={ x => x.id}
getOptionValue={ x => x.industry}
onChange={(e) => this.handleSelectChange(e, "industry")}
isMulti
/>
and handleSelectChange-
handleSelectChange = (e, name) => {
console.log(e)
if(e.length < 6){
return this.setState({
[name]: e
})
}
}
and state -
this.state = { industry: [] }
I am sharing my complete working component I think it can help>>
import React, { useState } from 'react';
import Select from 'react-select';
import makeAnimated from 'react-select/animated';
const animatedComponents = makeAnimated();
const ReactSelect = ({ data }) => {
const maxOptions = 5;
const [selectedOption, setSelectedOption] = useState([]);
const handleTypeSelect = e => {
setSelectedOption(e);
};
return (
<Select
onChange={handleTypeSelect}
getOptionLabel={x => x.name}
getOptionValue={x => x.slug}
components={animatedComponents}
isMulti
options={selectedOption.length === maxOptions ? [] : data}
noOptionsMessage={() => {
return selectedOption.length === maxOptions
? 'You have reached the max options value'
: 'No options available';
}}
label='tags'
/>
);
};
export default ReactSelect;
a very easy way to do this is:
<Select
value={tags}
onChange={(v) => v.length < 4 ? setTags(v): null}
isMulti
name='tags'
options={options}
className='basic-multi-select'
classNamePrefix='select'
/>
just add a simple ternary check for how many items you wants
I found the more simple and clean way, without extra manipulations. This way based on disabling an input component of 'react-select'. Take a closer look at the parameter inputProps
.
It can look like:
import Select from 'react-select';
import useField from 'client/components/hooks/useField';
const MultiSelect = ({
async,
creatable,
maxItems,
...restProps,
}) => {
const selectProps = {
...restProps,
// "inputProps: {disabled: boolean}" - our goal
...(typeof maxItems === 'number' && maxItems === restProps.value?.length ? {inputProps: {disabled: true}} : {})
};
const creatableTag = async ? Select.CreatableAsync : Select.Creatable;
const SelectTag = creatable ? creatableTag : selectTag;
return (
<div>
<SelectTag {...selectProps} />
</div>
);
};
const SomeComponentWithMultiSelect = () => {
const field = useField('data.name'); // field contains: {value: string[], ...}
const items = [
{
label: 'firstValue',
value: 1,
},
{
label: 'secondValue',
value: 2,
},
];
return (
<MultiSelect
items={items}
{...field}
creatable
maxItems={1} // {1} as our limit
/>
)
};
export default SomeComponentWithMultiSelect;
So you don't need to manage excess components.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.