React - MUI Autocomplete single selection remove event - javascript

I use material UI autocomplete to create a single-select dropdown.
But the problem is that when I click the close button placed right-side of the input, the onChange event didn't call and my state didn't update.
While in the multi-select mode this event successfully occurred.
Someone helps me to use the remove event in single-select mode.
This is my single select:
<Autocomplete<Option<T>>
onChange={(e: any, newValue) => {
if (newValue) {
handleChangeValue(newValue.value);
}
}}
sx={{ ...sx }}
id={id}
options={options}
isOptionEqualToValue={(newValue, option) =>
newValue.value === option.value
}
defaultValue={
defaultValue && {
value: defaultValue,
label: options.find((option) => option.value === defaultValue)?.label,
}
}
value={
value && {
value: value,
label: options.find((option) => option.value === value)?.label,
}
}
getOptionLabel={(option) => option.label || `${option.value}`}
renderOption={(props, option, { selected }) => (
<li value={option.value} {...props}>
<Checkbox
style={{ marginRight: 8 }}
checked={selected}
id={`${option.value}`}
/>
{option.label || `${option.value}`}
</li>
)}
renderInput={(params) => (
<TextField
value={value}
{...params}
placeholder={global.translate(placeholder)}
/>
)}
/>
this one is my multi-select autocomplete:
<Autocomplete
onChange={(e: any, value) => {
onChange(value);
}}
value={value}
sx={{ ...sx }}
multiple
id={id}
options={options}
disableCloseOnSelect
defaultValue={[...defaultValues]}
getOptionLabel={(option) => option.label}
isOptionEqualToValue={(newValue, option) =>
newValue.value === option.value
}
renderOption={(props, option, { selected }) => (
<li value={option.value} {...props}>
<Checkbox
icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
checkedIcon={<CheckBoxIcon fontSize="small" />}
style={{ marginRight: 8 }}
checked={selected}
id={option.value}
/>
{option.label}
</li>
)}
renderInput={(params) => (
<TextField {...params} placeholder={placeholder} />
)}
/>

In your single-select mode Autocomplete component, you send handleChangeValue if only newValue exists.
So, in your single-select mode, you need to change this code:
<Autocomplete<Option<T>>
onChange={(e: any, newValue) => {
if (newValue) {
handleChangeValue(newValue.value);
}
}}
to this code:
<Autocomplete<Option<T>>
onChange={(e: any, newValue) => {
const valueToBeSent = newValue ? newValue.value : undefined;
handleChangeValue(valueToBeSent);
}}
in order to send onChange event on every value change.

Related

React-Mui-AutoComplete not working correctly

mui autocomplete wont complete the text letter by letter by order its a bit of a mess , someone got a better autocomplete? or knows how to fix ? (example typing "l" will find first "agropoli" than "london")
<Autocomplete
id="free-solo-demo"
freeSolo
options={cityUniqe}
onChange={(event, value) => setSearch(value)}
renderInput={(params) => (
<TextField
{...params}
error={weatherData?.error ? true : false}
fullWidth
label="name your city here..."
value={search}
onChange={(e) => {
setSearch(e.target.value);
}}
ref={inputField}
onKeyDown={(e) => e.key === "Enter" && handleSubmit(e)}
/>
)}
/>
you need to kinda play with the filtration that happens under the hood, Mui provides a createFilterOptions method which you can use as follows:
import { Autocomplete, TextField, createFilterOptions } from "#mui/material";
export default function App() {
// create your filer options here
const filterOptions = createFilterOptions({
matchFrom: "start",
stringify: (option) => option
});
return (
<Autocomplete
id="free-solo-demo"
freeSolo
options={["agropoli", "london", "parlament"]}
filterOptions={filterOptions} // use them here
onChange={(event, value) => setSearch(value)}
renderInput={(params) => (
<TextField
{...params}
error={weatherData?.error ? true : false}
fullWidth
label="name your city here..."
value={search}
onChange={(e) => {
setSearch(e.target.value);
}}
ref={inputField}
onKeyDown={(e) => e.key === "Enter" && handleSubmit(e)}
/>
)}
/>
);
}

How reset value React Material UI Autocomplete using React Hook Forms

I have two autocomplete components in my form where one depends on the other. I want that at a choice of a field in the first component values in the second were reset. I tried a bunch of ways to do it, but nothing worked. Please, tell me how can I solve this problem?
return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmitAppealForm)}>
<Grid item container xs={12} sx={{ mt: 2 }} columnSpacing={3}>
<Grid item xs={6}>
<SelectControl
required
control={control}
options={[
{ id: 1, name: "1 - Тематика" },
{ id: 2, name: "2 - Категория" },
{ id: 3, name: "3 - Подкатегория" },
]}
placeholder="Уровень тематики"
label="Уровень тематики *"
name="themeLevel"
readonly
/>
</Grid>
<Grid item xs={6}>
<SelectControl
control={control}
options={getProjectThemesArray() ?? []}
disabled={!themeLevel || themeLevel === 1}
label="Родительская тематика"
defaultValue=""
name="parentThemeId"
loading={isParentThemeFetching}
/>
</Grid>
</Grid>
</form>
</FormProvider>
Autocomplete component:
return (
<>
<Controller
name={name}
control={control}
render={({ field: { value, onChange: handleChange } }) => (
<>
<div className="form-label">{label}</div>
<Autocomplete
onChange={(e, value) => {
handleChange(e, value);
onChange && onChange();
}}
options={options}
noOptionsText="Нет данных"
clearText=""
closeText=""
openText=""
autoHighlight
disabled={loading || disabled}
renderInput={(params) => (
<OutlinedInput
name={name}
{...params.InputProps}
inputProps={{
...params.inputProps,
}}
value={options.length > 1 ? value?.name : ""}
readOnly={readonly}
className={input}
required={required}
placeholder={
defaultValue && disabled
? defaultValue
: placeholder ?? label
}
fullWidth
/>
)}
isOptionEqualToValue={(option, value) => option.id === value.id}
getOptionLabel={(option) => option.name || ""}
renderOption={(props, option) => (
<MenuItem {...props} key={option.id} value={option.id}>
{option.name}
</MenuItem>
)}
popupIcon={
<div className={icon}>
{loading ? <Spinner width={20} height={20} /> : <Arrow />}
</div>
}
/>
</>
)}
/>
</>
I used reset and setField from useForm to my component but it didn't work. Also, resetting the state of the input did not work either.

How to set default selected items in Autocomplete

I am using material-ui Autocomplete and I want to add some default selected options to it.
https://codesandbox.io/s/broken-fire-htxtd?file=/src/App.js
As you can see in the example I am rendering pre-selected items with startAdornment. The problem is when I try to select another item, it automatically deletes the pre-selected items. Also I cannot delete them properly.
The idea is this default selected to stay selected until I remove them. Also to be able to pick another letter without erasing them.
you can use defaultValue property instead of Adornment.
<Autocomplete
multiple
open={open}
onOpen={() => {
setOpen(true);
}}
onClose={() => {
setOpen(false);
}}
options={["A", "B", "C", "D", "E"]}
disableCloseOnSelect
defaultValue={cities} //here
onChange={(e, v) => setCities(v)}
getOptionLabel={(option) => option}
renderOption={(option, { selected }) => {
if (cities.includes(option)) {
selected = true;
}
return (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option}
</React.Fragment>
);
}}
renderInput={(params) => {
return (
<TextField
{...params}
variant="outlined"
label="Cities"
placeholder="Enter cities"
autoComplete="off"
/>
);
}}
/>

React Material UI Autocomplete - how to display text name as select but send ID as a value?

MATERUAL UI Autocomplete component works fine, but I want to get object.id as onSelect event value (event.target.value), not the object.name. In other words, I want to display object.name as select item labels, but I want to get object.id as onSelect event value (event.target.value). Right now, my event.target.value is the same as select item label (object.name). Here is an example (from the Material UI documentation):
The options object is like this:
const options = [
{ id: "01", name: "Peter" },
{ id: "02", name: "Mary },
{ id: "03", name: "John" }
]
And the Autocomplete is the same like in Material UI documentation:
<Autocomplete
id="asynchronous-demo"
fullWidth
open={open}
onOpen={() => {
setOpen(true)
}}
onClose={() => {
setOpen(false)
}}
getOptionLabel={(option) => option.name}
options={options}
loading={loading}
renderInput={(params) => (
<TextField
{...params}
label="Asynchronous"
variant="outlined"
onChange={(event) => {
if (event.target.value !== '' || event.target.value !== null) {
onChangeHandle(event.target.value)
}
}}
onSelect={(event) => {
onSelectHandle(event)
}}
InputProps={{
...params.InputProps,
endAdornment: (
<React.Fragment>
{loading ? (
<CircularProgress color="inherit" size={20} />
) : null}
{params.InputProps.endAdornment}
</React.Fragment>
),
}}
/>
)}
/>
With onSelect I always get object.name as event.target.value, but I want to return object.id as event.target.value.
Does anybody knows how??
You are currently grabbing the value from TextField's onSelect, instead of Autocomplete's onChange.
<Autocomplete
...
onChange={(event, newValue) => {
onSelectHandle(newValue)
}}
renderInput={(params) => (
<TextField
{...params}
label="Asynchronous"
variant="outlined"
onChange={(event) => {
if (event.target.value !== '' || event.target.value !== null) {
onChangeHandle(event.target.value)
}
}}
...
/>
)}
/>
For more info, check out the controllable states section in the Autocomplete documentation.

Autocomplete Chip when multiple is false

I like the Chip option when multiple is true. Is there an option to enable Chip also when multiple is false ?
<Autocomplete
className={classes.search}
options={top100Films}
getOptionLabel={(option) => option.title}
multiple={false}
renderInput={(params) =>
<TextField {...params}
variant="outlined"
label="Customer's journey"
helperText="Search by: program"
/>}
/>
Thank you
No, unfortunately you would have to change the Autocomplete to a controlled component and do this yourself via the startAdornment prop on the Input. Something like:
function MyAutocomplete() {
const [value, setValue] = useState(null);
const chip = value ?
<Chip label={value.title} onDelete={() => setValue(null)} size="medium" />
: undefined;
return (
<Autocomplete
size="medium"
options={top100Films}
getOptionLabel={(option) => option.title}
onChange={(event, newValue) => setValue(newValue)}
value={value}
renderInput={(params) => (
<TextField
{...params}
InputProps={{
...params.InputProps,
startAdornment: chip
}}
variant="outlined"
label="Customer's journey"
helperText="Search by: program"
/>)}
/>);
}
Demo here

Categories