v4 material ui autocomplete is not resting value? - reactjs

I have the following advanced autocomplete logic in the past I used key to re render the whole component after submitting a form that is located else where any idea how to rest it the proper way ? my problem is I need to find a way to connect a value in to it a value that is connected to state some how and when my form will submit and the value will rest, (rest value will be triggered during submitting) so the autocomplete value will rest as well any idea how to integrate value using state in to this logic ?
const options = [{name : 'some option' , optionType : 'some type', tool : 'some tool'}, ...]
<Autocomplete
id='advancedselect'
ref={refAutocomplete}
options={options.sort((a, b) => -b.optionType.localeCompare(a.optionType))}
groupBy={(option: any) => option.optionType}
getOptionLabel={(option) => option.name}
renderOption={(option) => (
<React.Fragment>
<div style={{ width: '12vw', maxWidth: 75, marginRight: 10, padding: 0 }}>
<IconsOption img={option.tool} />
</div>
{option.name}
</React.Fragment>
)}
//value={val}
//onChange={(event) => setVal(event.currentTarget)}
//getOptionSelected={(option, value) => option.name === value.name}
PaperComponent={({ children }) => <Paper className={classes.backDrop}>{children}</Paper>}
PopperComponent={(props: any) => <Popper open={open.open} anchorEl={open.anchorEl} {...props} className={classes.popper} placement='bottom'></Popper>}
onClose={() => setOpen({ /*anchorEl: null,*/ ...open, open: false })}
onOpen={(event: any) => {
const { currentTarget } = event;
setOpen({
anchorEl: currentTarget,
open: true,
});
}}
onInputChange={handleAutoComplete}
className={classes.root}
renderInput={(params) => (
<TextField
name='field'
error={err.exercise ? true : false}
onChange={handleTextField}
{...params}
InputLabelProps={{ shrink: false }}
label={!text.length && !selected.stateOptions? `Selectd Opitons !!` : ' '}
onBlur={restTextOnBlurCond}
autoComplete='off'
/>
)}
/>

Related

value returns 0 or undefined on MUI autocomplete unable to fetch the value in multiple attribute

On MUI Autocomplete component where the attribute is multiple, then the value prop returns 0 or undefined when we choose anyone of the selected option.
<Autocomplete
value={v.education}
onChange={handleEducationChange}
className={classes.textOutline}
multiple
id="virtualize-demo"
name="education"
style={{ width: 600 }}
disableCloseOnSelect
ListboxComponent={ListboxComponent}
options={educationList()}
getOptionLabel={(option) => option.title}
isOptionEqualToValue={(option, value) =>
option.title === value.title
}
renderOption={(props, option, { selected }) => (
<li {...props}>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option.title}
</li>
)}
renderInput={(params) => (
<TextField
{...params}
variant="outlined"
name="education"
placeholder="Select your Qualification"
label="Education"
fullWidth
/>
)}
/>
// handleEducationChange
const initialState = { education: "", occupation: "" };
const [selectedOption, setSelectedOption] = useState([], initialState);
const handleEducationChange = (event) => {
const { name, values } = event.target;
setSelectedOption({ ...selectedOption, [name]: values });
console.log(values);
};
I need the selected value to be passed with value prop and that can be validated and posted to backend... kindly update the solution for this, Thanks.

Material UI: How do I reset inputValue when using InputBase for Autocomplete?

The following will allow you to prepare your own behavior like the one in the title, but it is not possible to do it in the following way
However, since debounce() is called each time onInputChange is performed, if the key is pressed for a long time
This method is not realistic because the processing becomes heavy and the input value becomes choppy.
How can the inputBase value be reset in such a case?
const [q, setQ] = useState('');
const handleInputChange = (
e: React.ChangeEvent<HTMLInputElement>,
value: string
) => {
setQ(value);
debounce(value);
};
const handleClickClear = () => {
setQ('');
debounce('');
};
<Autocomplete
getOptionLabel={(option) =>
typeof option === "string" ? option : option.word
}
inputValue={q}
options={data}
renderInput={(params) => (
<div ref={params.InputProps.ref}>
<InputBase
inputProps={{
...params.inputProps,
name: "search",
type: "text",
}}
/>
{q && (
<ButtonBase onClick={handleClickClear}>
<IconButton size="small">
<ClearIcon fontSize="small" />
</IconButton>
</ButtonBase>
)}
</div>
)}
blurOnSelect
freeSolo
openOnFocus
onChange={handleChange}
onFocus={handleFocus}
onInputChange={handleInputChange}
/>;

How can I set onDelete prop in autocomplete?

I want to delete chips thanks to an handleDelete function called in ChipProps but it seems not to be able to get the event.target.value... How can I do?
const handleDelete = (event) =>
{
console.log(event.target); // here I get undefined
}
<AutoComplete
multiple
id="checkboxes-options"
debug
options={newData.map((item) => item.name)}
ChipProps={{ clickable: false, onDelete: handleDelete, variant: "outlined", color: "primary" }}
disableCloseOnSelect
disableClearable
value={newData}
tag={{ color: "primary" }}
renderOption={(options, { selected }) =>
<Aux>
<FormControlLabel
control={
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 20 }}
value={options}
name={options === newData ? "isChecked" : "isUnchecked"}
color='primary'
checked={options === newData ? state.isChecked : selected}
onChange={updateNewData}
/>
}
/>
{options}
/>
Add a render function to the renderTags prop of your autocomplete component. Inside your renderTags method you can not only change your tags, but also override the onDelete function.
<Autocomplete
...
renderTags={(values) =>
values.map((value) => (
<Chip
key={value.id}
label={value.title}
onDelete={() => {
removeOption(value.id);
}}
/>
))
}
/>
Here is a reference to a similar question, which also has a demo:
Material UI Autocomplete - unchecking checkboxes in renderOption using Redux dispatch

Material-UI Autocomplete onChange not updates value

I want to use onChange event on Autocomplete component to get current selected values.
The problem is that it does not working as expected, so when I click to check/uncheck value checkbox is still unchecked but in console i can see that new value was added
uncoment this part to make it works:
value={myTempVal}
onChange={(event, newValue) => {
setMyTempVal(newValue);
console.log(newValue);
}}
online demo:
https://codesandbox.io/embed/hardcore-snowflake-7chnc?fontsize=14&hidenavigation=1&theme=dark
code:
const [myTempVal, setMyTempVal] = React.useState([]);
<Autocomplete
open
multiple
value={myTempVal}
onChange={(event, newValue) => {
setMyTempVal(newValue);
console.log(newValue);
}}
disableCloseOnSelect
disablePortal
renderTags={() => null}
noOptionsText="No labels"
renderOption={(option, { selected }) => {
return (
<>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option.title}
</>
);
}}
options={option2}
// groupBy={option => option.groupName}
getOptionLabel={option => option.title}
renderInput={params => (
<div>
<div>
<SearchIcon />
</div>
<TextField
variant="outlined"
fullWidth
ref={params.InputProps.ref}
inputProps={params.inputProps}
/>
</div>
)}
/>
You need to get donors receivers and options variables out of the function. Those variables get re-created at each render, this means that their reference changes at each render, and as Autocomplete makes a reference equality check to decide if an option is selected he never finds the options selected.
const donors = [...new Set(data.map(row => row.donor))].map(row => {
return {
groupName: "Donors",
type: "donor",
title: row || "null"
};
});
const receivers = [...new Set(data.map(row => row.receiver))].map(row => {
return {
groupName: "Receivers",
type: "receiver",
title: row || "null"
};
});
const option2 = [...donors, ...receivers];
export const App = props => {
const [myTempVal, setMyTempVal] = React.useState([]);
return (
<Autocomplete
open
multiple
...
You can also add getOptionSelected to overwrite the reference check :
<Autocomplete
open
multiple
disableCloseOnSelect
disablePortal
renderTags={() => null}
noOptionsText="No labels"
getOptionSelected={(option, value) => option.title === value.title}
renderOption={(option, { selected }) => {
return (
<>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option.title}
</>
);
}}
options={option2}
// groupBy={option => option.groupName}
getOptionLabel={option => option.title}
renderInput={params => (
<div>
<div>
<SearchIcon />
</div>
<TextField
variant="outlined"
fullWidth
ref={params.InputProps.ref}
inputProps={params.inputProps}
/>
</div>
)}
/>
This can help:
Replace
checked={selected}
To
checked={myTempVal.filter(obj=>obj.title===option.title).length!==0}
The complete solution
import React from "react";
import "./styles.css";
import TextField from "#material-ui/core/TextField";
import Autocomplete from "#material-ui/lab/Autocomplete";
import CheckBoxOutlineBlankIcon from "#material-ui/icons/CheckBoxOutlineBlank";
import CheckBoxIcon from "#material-ui/icons/CheckBox";
import Checkbox from "#material-ui/core/Checkbox";
import SearchIcon from "#material-ui/icons/Search";
const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;
const data = [
{ donor: "Trader Joe's", receiver: "Person-to-Person" },
{ donor: "Trader Joe's", receiver: "Homes with Hope" },
{ donor: "Santa Maria", receiver: "Gillespie Center" },
{ donor: "Santa Maria", receiver: null }
];
export const App = props => {
const donors = [...new Set(data.map(row => row.donor))].map(row => {
return {
groupName: "Donors",
type: "donor",
title: row || "null"
};
});
const receivers = [...new Set(data.map(row => row.receiver))].map(row => {
return {
groupName: "Receivers",
type: "receiver",
title: row || "null"
};
});
const option2 = [...donors, ...receivers];
const [myTempVal, setMyTempVal] = React.useState([]);
return (
<Autocomplete
open
multiple
value={myTempVal}
disableCloseOnSelect
disablePortal
renderTags={() => null}
noOptionsText="No labels"
renderOption={(option, { selected }) => {
return (
<>
<Checkbox
onClick={
()=>{
if(myTempVal.filter(obj=>obj.title===option.title).length!==0){
setMyTempVal([...myTempVal.filter(obj=>obj.title!==option.title)],console.log(myTempVal))
}else{
setMyTempVal([...myTempVal.filter(obj=>obj.title!==option.title),option],console.log(myTempVal))
}
}
}
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={myTempVal.filter(obj=>obj.title===option.title).length!==0}
/>
{option.title}
</>
);
}}
options={option2}
// groupBy={option => option.groupName}
getOptionLabel={option => option.title}
renderInput={params => (
<div>
<div>
<SearchIcon />
</div>
<TextField
variant="outlined"
fullWidth
ref={params.InputProps.ref}
inputProps={params.inputProps}
/>
</div>
)}
/>
);
};
export default App;
It is bit late to Answer this question but it might help someone.
In your code you have added onChange event in Autocomplete. When you click on checkbox it will trigger 2 times, one for checkbox and one for Autocomplte. Hence 2nd time trigger makes again checkbox unchecked so u get value in console but still checkbox is empty.
You can remove your checkbox in renderOption and use checked and uncheked icon instaed of checkbox.
renderOption={(option, { selected }) => {
return (
<React.Fragment>
{selected ? <CheckedIcon> : <uncheckedIcon>}
<div>
{option.title}
</div>
</React.Fragment>
</>
);
}}

How to use onchange with autocomplete material ui?

With the method handleChange is handled OnChange event of the Form Input with Hooks style that set the state off the object.
The handleChange function in turn calls setLocation which updates the location state with the new value.
To make user data entry easier, I decided to change the city field to an autocomplete, but I failed to capture the value of the autocomplete.
In the documentation he tells me that I need to pass two arguments but I can't understand very well
function(event: object, value: any) => void
event: The event source of the callback
value: null
How can I access the value of the field and put it into my function to insert the data?
<Autocomplete
style={{ width: 300 }}
value={location.City}
onChange={handleChange}
options={list.City}
classes={{
option: classes.option,
}}
autoHighlight
getOptionLabel={option => typeof option === 'string' ? option : option.City}
renderOption={option => (
<React.Fragment>
{option.City} -{option.State}
</React.Fragment>
)}
renderInput={params => (
<TextField {...params} label="City" value={location.City} margin="normal" variant="outlined" style={{ width: 220 }} inputProps={{
...params.inputProps,
autoComplete: 'disabled', // disable autocomplete and autofill
}}/>
)}
/>
If you're just trying to get the value of the input as the user types, you need to use onInputChange. The onChange handler runs when the user selects an option from the drop down.
export default function ComboBox() {
function handleInputChange(event, value) {
console.log(value);
}
return (
<Autocomplete
id="combo-box-demo"
options={top100Films}
getOptionLabel={(option: FilmOptionType) => option.title}
style={{ width: 300 }}
onInputChange={handleInputChange}
renderInput={params => (
<TextField {...params} label="Combo box" variant="outlined" fullWidth />
)}
/>
);
}
Codesandbox
the react SyntheticEvent set null target in an Asynchronous requests, try to use
event.persist()
on the event
https://reactjs.org/docs/events.html#event-pooling
const handleOnChangeText=(event)=> {
event.persist();
console.log(event)
let active = true;
setOpen(true);
if (!loading) {
return undefined;
}
(async () => {
const response = await fetch('https://country.register.gov.uk/records.json?page-size=5000');
await sleep(1e3); // For demo purposes.
const countries = await response.json();
if (active) {
setOptions(Object.keys(countries).map(key => countries[key].item[0]) as CountryType[]);
}
active = false;
})();
}
<Autocomplete
id="comboboxAsync"
disableOpenOnFocus
style={{ width: 300 }}
open={open}
onInputChange={handleOnChangeText}
...
Id is getting retrieved under this pattern: id-option-numberOfOption, that's why I had to split the retrieved value in order to update the state
const handleAutoCompleteChange = (event, value) => {
this.setState({ ...this.state, [event.target.id.split("-")[0]]: value });
console.log([event.target.id.split("-")[0]],value);
}
You can use mui-autocomplete npm its easy and less coding with more options(Like avatar view asynchronus calls).You should try it out. Here is the example for more info visit here.
[http://mui-autocomplete.com/home]
`import React from 'react';
import MuiAutocomplete from 'mui-autocomplete';
const cities = [
{
id: 1,
name: "Alabama",
code: "AL"
},
{
id: 2,
name: "Alaska",
code: "AK"
},
{
id: 3,
name: "American Samoa",
code: "AS"
}];
function Home () {
return (
<div>
<MuiAutocomplete
placeholder="Countries"
name="countries"
setvalue={1}
setdata={cities}
variant="outlined"
template={{
title: 'name'
}}
/>
</div>
);
}`

Resources