How to change closeMenuOnSelect value on event in react-select? - reactjs

I am trying to close the Select dropdown when the limit of selected items is reached.
The following is not working:
handleSearch = selectedOption => {
const closeMenuOnSelect = selectedOption.length >= 3;
this.setState({ closeMenuOnSelect }, () => this.updateSelect());
}
updateSelect = () => {
console.log(this.state.closeMenuOnSelect); // the state is getting updated but it does not have the effect on the `closeMenuOnSelect` property
}
And the component:
<Select className='react-select-container'
isMulti
closeMenuOnSelect={this.state.closeMenuOnSelect}
options={this.state.locations}
onChange={(e) => this.handleSearch(e)} />
It doesn't need to on event. I just want the menu to remain open and when the limit of selected options is reached I want to close it.

There is a prop "menuIsOpen" in React Select and by using it you can control the open or close of dropDown
const [showMenu, setShowMenu] = useState(false);
<Select className='react-select-container'
isMulti
options={this.state.locations}
onChange={(e) => this.handleSearch(e)}
menuIsOpen={showMenu}
onBlur={() => setShowMenu(false)}
blurInputOnSelect
/>
So now you can call setShowMenu(true) / setShowMenu(false) to show or hide the select menu as per your need.

Related

How to catch remove event in React-select library

I want to change the state whenever I delete an element from the react-select multi varient select option.
There is a second param in the onChange function for react-select, where it captures the context, meaning it has information about what action is performed or what element got removed.
const onChange = (value, context) => {
// console.log(value);
if (context.action === "remove-value") {
console.log(context.removedValue.id);
const newState = newitems.filter(
(item) => item.id !== context.removedValue.id
);
setnewitems(newState);
}};
<Select
isMulti
options={options}
onChange={onChange}
/>

How to reset my filter options to their initial blank state? React

I have some input boxes, select drop down, and date picker that are not being reset like I thought they would. Let's start with the input box and select drop down. Here is their code:
<StyledInput
onChange={handleSearchChange}
value={searchText}
placeholder={"Search..."}
/>
<SelectDropDown
isClearable={false}
isSearchable={false}
strict={true}
allowInvalid={false}
getOptionLabel={opt => opt.name}
getOptionValue={opt => opt.value}
value={searchOptions.find(opt => opt.value === searchCol)}
options={searchOptions}
onChange={value => {
handleColSelect(value);
}}
/>
Notice the handleSearchChange and handleColSelect:
const handleColSelect = value => {
setSearchCol(value.value);
};
const handleSearchChange = event => {
setSearchText(event.target.value);
};
I have a button that I want to reset these to their initial states (i.e. get rid of text in the input box, and reset the SelectDropDown).
I've tried doing so:
const clearFilters = () => {
setSearchText(undefined);
setStartDate(undefined);
setEndDate(undefined);
setSearchCol(undefined);
};
And in my button, simply this:
<GreenOutlineButton
onClick={() => {
clearFilters();
}}
>
Clear Filters
</GreenOutlineButton>
There is another part to this to remove the queryParams that are set, and my button does so- however, it does not take away the text or reset the dropdown. Any ideas here?
From the look of it, setSearchText("") should work fine. For the SelectDropDown, you need to add one more entry to the options which will be your default entry. You can do this as follows:
options={[...searchOptions,{label:"Placeholder", value: null}]}
Then, inside clearFilters, use:
setSearchCol(null)
This should give you the desired result. Let me know if this works.

Selecting created option on menu close/select blur using creatable component

Is there some way to instruct react-select to select an option on menu close or select blur, but only if it is the one created (not from default list)?
Context:
I have a list of e-mail addresses and want to allow user to select from the list or type new e-mail address and then hit Submit button. I do the select part with react-select's Creatable component and it works.
import CreatableSelect from 'react-select/creatable';
<CreatableSelect
options={options}
isMulti={true}
isSearchable={true}
name={'emailAddresses'}
hideSelectedOptions={true}
isValidNewOption={(inputValue) => validateEmail(inputValue)}
/>
But what happens to my users is that they type new e-mail address, do not understand they need to click the newly created option in dropdown menu and directly hit the Submit button of the form. Thus the menu closes because select's focus is stolen and form is submitted with no e-mail address selected.
I look for a way how can I select the created option before the menu is closed and the typed option disappears.
You can keep track of the inputValue and add the inputValue as a new option when the onMenuClose and onBlur callbacks are triggered.
Keep in mind that both onBlur and onMenuClose will fire if you click anywhere outside of the select area. onMenuClose can also fire alone without onBlur if you press Esc key so you will need to write additional logic to handle that extra edge case.
function MySelect() {
const [value, setValue] = React.useState([]);
const [inputValue, setInputValue] = React.useState("");
const isInputPreviouslyBlurred = React.useRef(false);
const createOptionFromInputValue = () => {
if (!inputValue) return;
setValue((v) => {
return [...(v ? v : []), { label: inputValue, value: inputValue }];
});
};
const onInputBlur = () => {
isInputPreviouslyBlurred.current = true;
createOptionFromInputValue();
};
const onMenuClose = () => {
if (!isInputPreviouslyBlurred.current) {
createOptionFromInputValue();
}
else {} // option's already been created from the input blur event. Skip.
isInputPreviouslyBlurred.current = false;
};
return (
<CreatableSelect
isMulti
value={value}
onChange={setValue}
inputValue={inputValue}
onInputChange={setInputValue}
options={options}
onMenuClose={onMenuClose}
onBlur={onInputBlur}
/>
);
}
Live Demo

How can i define a default value for react-select v1

I had a react-select rendering a list of emails, and i need to keep the selected emails as a default option when the email is selected and saved, but the defaultValues are not working. How can i do that?
Here is my select component:
const [selectedOption, setSelectedOption] = useState("")
const makeEmailOption = item => ({
value: item.id,
label: item.ccEmail,
id: item.id,
chipLabel: item.ccEmail,
rest: item,
selected: item.selected
})
const makeEmailOptions = items => items.map(makeEmailOption)
const handleChange = (value) => {
setSelectedOption(value)
props.emails(value)
}
return (
<div>
<Select
multi={true}
name={props.name}
options={makeEmailOptions(props.ccemailfilter)}
onChange={handleChange}
value={selectedOption}
/>
</div>
)
I receive everything as props and work with that to make the options. How can i do that to make the default value if a field selected is true?
You almost have it, but in this case, you are setting the value to the selectedOption instead of setting the defaultValue. Also, you are changing the default value each time there is a change, which shouldn't be needed.
const defaultVal = {value: selectedOption, label: selectedOption};
return (
<div>
<Select
multi={true}
name={props.name}
options={makeEmailOptions(props.ccemailfilter)}
defaultValue={defaultVal}
/>
</div>
)
I came with the following solution, since my component use a function to set some variables to the select, i use a useEffect to call that with a filter right after the page render.
useEffect(() => {
handleChange(makeEmailOption(props.ccemailfilter.filter(x => x.selected)))
}, [])
const handleChange = (value) => {
setSelectedOption(value)
props.emails(value)
}
So, the handleChange are called on the onChange of the select and once after the page loads, to create a value to the select to use.

Programmatically close react-select menu

React-select default behavior is to have the menu pop open when the input value is empty. I want to modify this behavior so that when the input is empty, whether before a user has typed anything or the user has backspaced to get to the empty state, the menu will be closed.
I could not find any prop that enables this behavior, so I thought to do it programmatically, by calling some function that closes the menu in onInputChange. Something like:
onInputChange={(inputValue) => {
this.setState({
inputValue,
});
this.selectRef.closeMenu();
}}
I tried using blur() on the Select ref but it just blurred the input without closing the menu, definitely not the behavior I'm looking for.
Is there a prop or function that's exposed that can fulfill my needs?
You can set the menuIsOpen prop onInputChange like this:
handleInputChange = input => {
this.setState({ open: !!input });
}
<Select
onInputChange={this.handleInputChange}
menuIsOpen={this.state.open}
/>
I kept the open state separately
const [open, setOpen] = useState(false);
<Select
menuIsOpen={open}
onMenuOpen={() => setOpen(true)}
onMenuClose={() => setOpen(false)}
/>
and set false when I want to close it. In this case, like this
onInputChange={(text) => {
if (text === '') {
setOpen(false);
}
}}

Resources