I'm trying to customize material-ui dropdown, to make it something like this,
here is the link https://codesandbox.io/s/busy-black-2fgdn?file=/src/App.js,
if I write 1 in the input (from) it selects the option that starts with 1 instead of writing in input, if none of the options starts with the number entered in the input then it writes in the input,
Use Autocomplete with freeSolo as a prop.
check the docs here => https://mui.com/components/autocomplete/#free-solo
const dataList = [
{ title: "10-100", value: "10-100" },
{ title: "100-200", value: "100-200" },
{ title: "200-300", value: "200-300" },
{ title: "300-400", value: "300-400" }
];
...
<Autocomplete
id="free-solo-demo"
freeSolo
options={dataList.map(option => option.title)}
renderInput={params => <TextField {...params} label="select or type" />}
/>
code sandbox => https://codesandbox.io/s/winter-cloud-y401t?file=/src/App.js
Related
I am creating an Autocomplete element using Material UI, React Hook Form, and Yup that allows a user to choose multiple inputs for the days of the week.
If a user chooses the "Every day" option, I want to disable being able to choose Sunday, Monday, Tues... etc. How would I do that using getOptionDisabled?
Here is my current code...
const daysOfWeekSuggestions = [
{label: "Every day"},
{label: "Sunday"},
{label: "Monday"},
{label: "Tuesday"},
{label: "Wednesday"},
{label: "Thursday"},
{label: "Friday"},
{label: "Saturday"}
];
<Autocomplete
disableClearable
disablePortal
filterSelectedOptions
multiple
getOptionLabel={(option) => option.label}
id="days-autocomplete"
options={daysOfWeekSuggestions}
renderInput={(params) => <TextField
required
error={errors.daysOfWeek ? true : false}
id="daysOfWeek"
label="Days of the week"
name="daysOfWeek"
type="search"
{...params}
{...register("daysOfWeek")}
/>}
/>
What you need to do is use the getOptionDisabled prop and then check to see if the user has already selected Every Day. Im guessing you are saving it into state similar to how I am using it here so you can then just use the .some function to see if the Every day object is in the values array.
const daysOfWeekSuggestions = [
{ label: "Every day" },
{ label: "Sunday" },
{ label: "Monday" },
{ label: "Tuesday" },
{ label: "Wednesday" },
{ label: "Thursday" },
{ label: "Friday" },
{ label: "Saturday" }
];
export default function DaysOfTheWeekSelect() {
const [value, setValue] = React.useState([]);
const handleOnChange = (e, value) => {
setValue(value);
};
return (
<Autocomplete
disableClearable
disablePortal
multiple
getOptionLabel={(option) => option.label}
id="days-autocomplete"
onChange={handleOnChange}
options={daysOfWeekSuggestions}
getOptionDisabled={(option) => {
if (value.some((day) => day.label === "Every day")) {
return true;
}
if (value.some((day) => day.label === option.label)) {
return true;
}
return false;
}}
value={value}
renderInput={(params) => (
<TextField
required
error={errors.daysOfWeek ? true : false}
id="daysOfWeek"
label="Days of the week"
name="daysOfWeek"
type="search"
{...params}
{...register("daysOfWeek")}
/>
)}
/>
);
}
I also made it that if you have already selected a value then it would be disabled as well. Just seems a little bit better than just filtering out the selected values
I think you need more than just getOptionDisabled option.
I have done similar thing in my prev app, for that you need to add one more property called disabled to each option and onChange to Every day, manually disable remaining options.
You can check working demo here - https://codesandbox.io/s/disable-mui-autocomplete-options-on-condition-gurzb
Try using the isOptionEqualToValue instead
<Autocomplete
...
isOptionEqualToValue={(option, value) => option.id === value.id}
...
/>
supply the identifying property, in this case 'id'
I have a Autocomplete multiple select element. When I click on cross, to delete some option, I want to get this value. I tried to use ChipProps = {{onDelete: some function}} but it did not work :( I get undefined, and more over, delete function stops to work at all.
Here is my code
const top100Films = [
{ title: 'The Shawshank Redemption', year: 1994 },
{ title: 'The Godfather', year: 1972 },
{ title: 'The Godfather: Part II', year: 1974 },
{ title: 'The Dark Knight', year: 2008 },
{ title: '12 Angry Men', year: 1957 },
{ title: "Schindler's List", year: 1993 },
];
<Autocomplete
multiple
id="tags-standard1"
options={top100Films}
getOptionLabel={(option) => option.title}
//ChipProps = {{onDelete: (option) => {console.log(option.title)}}}
renderInput={(params) => (
<TextField
{...params}
size="small"
variant="outlined"
label="Films"
/>
)}
/>
So could anybody tell me how to get Id, or value, of deleted option?
As from this MR: https://github.com/mui-org/material-ui/pull/19959/files, if you need the whole removed object you can use the fourth argument. For example:
onChange={(event, list, reason, detail) => {
if (reason === 'remove-option') {
console.log(detail.option);
};
})
I can confirm the deletion stops working if you add onDelete handler in ChipProps. I believe that it's a bug from Material-UI side. In the meantime you probably want to use the following hack to get the value of the chip when deleted:
<Autocomplete
multiple
options={top100Films}
fullWidth
getOptionLabel={(option) => option.title}
onChange={(e, option, reason) => {
if (reason === "remove-option") {
console.log("delete", e.currentTarget.parentElement.innerText);
}
if (reason === "clear") {
console.log("clear all");
}
}}
{...}
/>
Live Demo
onChange={(e, value, situation, option) => {
if (situation === "removeOption") {
//write your code here
console.log("--->", e, value, situation, option);
}
setReceivers((state) => value);
}}
now it's removeOption not remove-option
when i try to change the value in autocomplete of material-ui, i always get its value 0, here i have uploaded my whole code, can anyone please check my code and help me to resolve this issue ?
any help will be really appreciated.
export default function CreatePIC() {
const classes = useStyles();
const Department_list = [
{ label: 'Department1', id: 1 },
{ label: 'Department2', id: 2 },
{ label: 'Department3', id: 3 },
{ label: 'Department4', id: 4},
{ label: 'Department5', id: 5 }
]
const [department, setDepartment] = React.useState('');
const handleChangeDepartment = (event) => {
console.log(event.target.value);
setDepartment(event.target.value);
};
return (
<Autocomplete
id="Department"
value={department}
helperText={error.department}
options={Department_list}
getOptionLabel={option => typeof option === 'string' ? option : option.label}
onChange = {handleChangeDepartment}
renderInput={(params) => <TextField {...params} label="Search Department" variant="outlined" placeholder="Add Department" />}
/>
)
}
Ciao, in Autocomplete component event.target.value will be always 0. If you want to get the selected department you could use value in handleChangeDepartment. So your code becomes:
const handleChangeDepartment = (event, values) => {
console.log(event.target.value); // print always 0
console.log(values); // print values selected like { label: 'Department1', id: 1 }
setDepartment(values.label); // set department with values.label
};
Here a codesandbox example.
Rather than using:
event.target.value
try using:
event.target.innerText
or, to find the option index, use:
event.target.dataset.optionIndex
Below is a snippet of how I call the Select menu:
import Select from 'react-select';
const SelectMenu = (props) => {
const { options, defaultValue, onChange, name, label } = props;
return (
<Select
options={options}
defaultValue={defaultValue}
onChange={onChange}
name={name}
id="search-select"
/>
);
};
My options object looks as follows:
TestObj: [
{
label: 'Test 1',
value: 3.49
},
{
label: 'Test 2',
value: 3.99
},
{
label: 'Test 3',
value: 3.89
},
{
label: 'Test 4',
value: 3.99
},
{
label: 'Test 5',
value: 0
}
]
Because of the fact two of the options share the same value I get this effect:
As can be seen due to Test 2 and 4 sharing the same value they both show as selected.
Is there a way that whilst keeping the same values I can have this so that it only selects the actual selected option?
The way react-select by default checks if a value is selected is by extracting the value piece and comparing it to whats selected (an array of objects with a value key.)
Using isOptionSelected you can override the strategy employed:
isOptionSelected={(option, selectValue) => selectValue.some(i => i === option)}
This is more or less how the internal function works without extracting the value part, and instead compares the whole object.
Is there a way to change the fields of an option object?
From my BE API i get:
const items = [{ id: 1, name:'dropdown1'}, { id: 2, name:'dropdown2'}];
So now i have to remap the fields to value and label, it would have been nice if i could set those fields dynamically, maybe something like:
<Select
optionRemapping={{value: 'id', label: 'name'}}
options={items}
/>
Or maybe i have missed a pattern on how people do this?
Doing the below feels a bit wrong.
items.map((item) => {
return { value: item.id, label: item.name };
});
Use getOptionLabel and getOptionValue props.
<Select
getOptionLabel={option => option.name}
getOptionValue={option => option.id}
options={items}
/>
example : https://codesandbox.io/s/kmoyw8q667
You could achieve your mapping by doing the following and deconstructing your items :
<Select
options={items.map(({ id, name }) => ({ value: id, label: name}))}
/>