react-select: Automatically suggest "other" option when you have no options for the search - reactjs

I have a searchable dropdown field on my form, where the user does the research and selects normally.
What I need is if he types an option that does not exist, suggest the option "other" for him to select.
The "other" option already exists, I just don't know how to automatically suggest it.
I've seen about noOptionsMessage, but it's not useful for me, I need you to suggest the option automatically.
Can you help me? Thanks.

There is a props called filterOption to customize how you want your option filtered when the user types in the input, but it can only filter a single option and lacks the context of other options.
Because of that, to show the "other" option when no option available, you have to:
Disable the default option filter so it doesn't mess with your custom filter.
Control the options state.
Filter out the options as the user type and update the options state.
Below is an example to demonstrate what I meant:
import Select, { createFilter } from "react-select";
const filterOption = createFilter({});
const allOptions = [
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" }
];
const otherOption = { value: "other", label: "Other" };
export default function App() {
const [options, setOptions] = useState(allOptions);
const filterAllOptions = (rawInput: string) => {
const filteredOptions = allOptions.filter((o) => filterOption(o, rawInput));
if (filteredOptions.length === 0) {
filteredOptions.push(otherOption);
}
setOptions(filteredOptions);
};
return (
<Select
options={options}
filterOption={() => true} // disable the default option filter
onInputChange={(e) => filterAllOptions(e)}
/>
);
}
Live Demo

Related

Use Antd select with mode tags but allow only one selection

I'm using Antd Select for a project. My requirement is to use Select with mode='tags' as it allows user to create a new option, but I also want user to select only one option at a time (i.e either have a new option created or have an existing option selected shown in the select box). I tried using autoClearSearchValue but is of no use.
Appreciate the help.
Make the <Select /> to be controlled component.
I write an example, the key logic is to control the selected value in onChange function;
export default function MyTest() {
const [data, setData] = React.useState<string[]>([]);
return (
<div>
<Select
mode="tags"
onChange={(value, options) => {
// update data only when select one item or clear action
if (options?.length === 0 || options?.length === 1) {
setData(value);
}
}}
value={data}
options={[
{
label: "0",
value: "0",
},
{
label: "1",
value: "1",
},
{
label: "2",
value: "2",
},
]}
/>
</div>
);
}

How to make MUI's Autocomplete display the label from the matching value in props.options?

I have a multilingual website where there are certain Autocompletes whose options array need to have its items labels translated, which is done very easily.
However, it would be harder to update the current chosen value, stored elsewhere. Since Autocomplete uses the label from the value prop instead of using the item of same ID within options, it ends up like this:
const vehicles = [
{ id: 1, label: "Car" },
{ id: 2, label: "Bus" }
];
const currentVehicleValue = {
id: 2,
label: "Ônibus"
};
export default function ComboBox() {
return (
<Autocomplete
disablePortal
id="combo-box-demo"
options={vehicles}
value={currentVehicleValue}
renderInput={(params) => <TextField {...params} label="Vehicle" />}
/>
);
}
Is there a way to just tell Autocomplete to use the label inside the options prop instead of the one within the value
demo
EDIT: I mean to have the label within options being shown while I don't type anything. As in, the language changed, the options were translated, but the currentValue was not, so it would be nice to have the Autocomplete use the label from the matching item within options as long as I don't type anything.
Edit after clarification
You can change how the <TextField/> is rendered by tweaking the props it receives.
In the example below, I find the currentVehicle by its id and change the inputProps.value to be the vehicle label.
Also, to ensure MUI finds the currentValue correctly within the options, you will need to use the isOptionEqualToValue to compare the options ids instead of strict equality
const vehicles = [
{ id: 1, label: "Car" },
{ id: 2, label: "Bus" }
];
const currentVehicleValue = {
id: 2,
label: "Ônibus"
};
function compareValueToOption(option, value) {
return option.id === value.id;
}
function ComboBox() {
return (
<Autocomplete
disablePortal
id="combo-box-demo"
options={vehicles}
value={currentVehicleValue}
renderInput={ComboBoxInput}
isOptionEqualToValue={compareValueToOption}
/>
);
}
function ComboBoxInput(props) {
const currentVehicle = vehicles.find(
(vehicle) => vehicle.id === currentVehicleValue.id
);
props.inputProps.value = currentVehicle.label;
return <TextField {...props} label="Vehicle" />;
}
Here's a working demo

How to set list of object as default values in material-UI multi select box in reactjs?

I have this example using multi select box from material-ui v4.
The example contains two components the first with a default value list of object that is not working properly and a second component with a list of string that works fine.
The problem: (first component) when I open the Select component the default values is not selected and when I click on the default value it added again to the select box I have the same value multiple time.
Use the same object, eg change.
const [personName, setPersonName] = React.useState([
{ _id: '1', name: 'Oliver Hansen' },
{ _id: '2', name: 'Van Henry' },
]);
to:
const [personName, setPersonName] = React.useState(names.slice(0,2));
I don't remember this being necessary previously with materialUI, but it fixes the problem in your demo, so maybe I just haven't run into it before.
This is what i tried Array.reduce (Shallow copy):
const namesCopy = names.reduce((newArray, element) => {
props.defaultList.map((item) => {
if (item._id === element._id) {
newArray.push(element);
}
});
return newArray;
}, []);
const [personName, setPersonName] = React.useState(namesCopy);

How to disable `deselect-option` in `react-select`?

I would like to use the react-select multi Select component and be able to select the same option multiple times. However, react-select does not allow one to do this. You can change the dropdown to show already selected options with hideSelectOptions={false}, but if you select one of them again, it will be deselected.
This issue #3234 describes this same problem and sugggests that one way to solve this problem is to handle the action argument to onChange somehow.
Here is the solution that I attempted based off of the suggested solution:
import React, { Component } from "react";
import Select from "react-select";
export default class MultiSelect extends Component<*, State> {
handleChange(option, action) {
console.log(option, action);
// return;
if (action === "deselect-option") {
action = "select-option";
// now how do I do the component's state?
}
}
render() {
return (
<Select
isMulti
className="basic-single"
classNamePrefix="select"
name="color"
options={[{"label": "hello", "value": "hello"}, {"label": "world", "value": "world"}]}
hideSelectedOptions={false}
onChange={this.handleChange}
/>
);
}
}
I expected to be able to enter "hello" multiple times but when I tried to enter "hello" again it was deleted.
In options, the data field makes value dynamic with any key, in this case, use Date.now() to make dynamic. then use actions 'select-option' to append to options, use actions 'remove-value'' to filter all fields in the Options data field with a label matching with selected option label and append to data and append one more object to Options datafield
options = [
{ value: Date.now(), label: "SUBJECT" ,val:"SUBJ" },
{ value: Date.now, label: "VERB", val:"VERB" }
]
<Select options={options} isMulti onChange={(e, option) => {
if (option.action === "select-option") {
Options=[
...Options,
{
value: option.option.value + "_" + Date.now(),
label: option.option.label
}
];
} else if (option.action === "remove-value" ||option.action === "pop-value") {
tempData = data.filter(opt => opt.label !== option.removedValue.label)
Options=[
...tempData,
{
value: option.removedValue.value + "_" + Date.now(),
label: option.removedValue.label
}
]
}
}
} />

React Grommet Select - passing in object data as options

I am using Grommet v2 components and trying to mirror the display used in the Select 'Seasons' example in Grommet's storybook.
The field appears like this:
The difference is my data needs to separate label and value:
const Options = [
{
label: "S01",
value: "283736"
},
{
label: "S02",
value: "293774"
},
instead of using the default:
const Options = [
"S01",
"S02",
Here is an example on Codesandbox
The object format was used in Grommet's example of ObjectMultiSelect in their storybook. I found the Select component needs
labelKey="label" and valueKey="value" to load the objects as options, but adding these two props seems to break the component options.
I would like for the data passed in to resemble
const Options = [
{
label: "S01",
value: "283736"
},
{
label: "S02",
value: "293774"
},
and still have the options displayed as above.
<Select
options={[
{
lab: "S01",
val: "283736"
},
{
lab: "S02",
value: "293774"
}
]}
labelKey="lab"
dropHeight="large"
name="primaryServer"
value={this.props.values.primaryServer}
placeholder="Select Primary Server"
emptySearchMessage={"No Servers Available"}
onChange={({ option }) => {
console.log(option.lab)
console.log(option.val)
}}
/>
// Output // S01 // 283736
// This worked for me. labelKey="lab" is required.

Resources