I am trying to implement the Autocomplete component into my project but am getting the autofill/autocomplete from the browser after some time. Do you know how I can set it to off ?
<Autocomplete
id="combo-box-demo"
options={battleRepos}
getOptionLabel={option => option.full_name}
style={{ width: 500 }}
renderInput={params => (
<TextField {...params}
label="Combo box"
variant="outlined"
onBlur={event => console.log(event.target.value)}
fullWidth />
)}
/>
UPDATE
With the release of #material-ui/core 4.7.0 and #material-ui/lab 4.0.0-alpha.33, this is now fixed and no longer requires the workaround shown below.
This has been fixed in a recent pull request, but is not yet released (will be in the next release).
If you want to work around this prior to it being released (which will likely be within a few days), you can set inputProps.autoComplete = "off" like in the following:
<Autocomplete
id="combo-box-demo"
options={battleRepos}
getOptionLabel={option => option.full_name}
style={{ width: 500 }}
renderInput={params => {
const inputProps = params.inputProps;
inputProps.autoComplete = "off";
return (
<TextField
{...params}
inputProps={inputProps}
label="Combo box"
variant="outlined"
onBlur={event => console.log(event.target.value)}
fullWidth
/>
);
}
}
/>
Even with the latest:
"#material-ui/core"
"#material-ui/lab"
which contains the autoComplete property set to 'off', I wasn't able to get the autofill box go away.
Also tried setting the attribute on the form tag <form autoComplete="off">...</form>
To no avail.
The thing which resolved the issue was setting the autoComplete field to 'new-password'
<Autocomplete
id='id'
options={data}
onChange={(e, val) => input.onChange(val)}
renderInput={(params) => {
params.inputProps.autoComplete = 'new-password';
return <TextField {...params}
label={label} placeholder="Type to Search" />
}}
/>
Related
I am using Formik in my React project to process forms and using MUI UI components.
I am able to pick the day, month, but the year part does not change. If I manually type in year in the textfield, the year part is not reflected in the changed state.
Here's my code:
<LocalizationProvider dateAdapter={DateAdapter}>
<DatePicker
name="birthday"
id="birthday"
variant="standard"
label="Birthday"
value={formik.values.birthday}
renderInput={(params) => (
<TextField {...params} variant="standard" fullWidth/>
)}
onChange={(value) => formik.setFieldValue('birthday', value, true)}
error={formik.touched.birthday && Boolean(formik.errors.birthday)}
helperText={formik.touched.birthday && formik.errors.birthday}
/>
</LocalizationProvider>
The initial state:
const initialFormState = {
birthday: Date.now(),
};
All the other components are working correctly and changes in state show immediately.
The onChange property is not set in the DatePicker component. You have to move the onChange property from TextField to DatePicker.
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
onChange={(value) => setFieldValue("birthday", value, true)}
value={values.birthday}
renderInput={(params) => (
<TextField
error={Boolean(touched.birthday && errors.birthday)}
helperText={touched.birthday && errors.birthday}
label="Birthday"
margin="normal"
name="birthday"
variant="standard"
fullWidth
{...params}
/>
)}
/>
</LocalizationProvider>
Also, the name, id, variant and label are TextField's properties.
Here is the working CodeSandbox link.
I'm using Material UI version 4 (the latest), and the Informed form library. I have a custom component (custom to integrate with Informed) that wraps the Material UI TextField which I'm rendering using the Autocomplete component.
App component
<Form getApi={(api) => setFormApi(api)}>
{formApi && (
<>
<label>
First name:
<Autocomplete
freeSolo
options={autoOptions}
renderInput={(params) => (
<CustomTextField field="name" {...params} />
)}
/>
</label>
<button type="submit">Submit</button>
<button type="button" onClick={() => formApi.reset()}>
Reset
</button>
<FormState />
</>
)}
</Form>
The issue
When the reset button is clicked you can see the Informed "form state" is cleared, but the input still has a value. Any ideas on how to solve this?
Example - Codesandbox
The inputProps are getting overriden by the ones provided by Autocomplete component, change the order you pass ...rest props and included the ...rest.inputProps in your custom inputProps with the correct value
<TextField
{...rest} // should go first to allow overriding
// only add value props for select fields
// value={value}
onChange={(event) => {
setValue(event.target.value);
if (onChange) {
onChange(event);
}
}}
onBlur={(event) => {
setTouched(true);
if (onBlur) {
onBlur(event);
}
}}
error={!!error}
helperText={error ? error : helperText ? helperText : false}
variant="outlined"
margin="none"
fullWidth
inputProps={{
...rest.inputProps, // must include otherwise it breaks
value:
!select && !maskedValue && maskedValue !== 0 ? "" : maskedValue,
maxLength: maxLength || undefined
}}
// eslint-disable-next-line
InputProps={{
style: sensitive && {
color: "rgba(0,0,0,0)",
caretColor: "#000"
},
startAdornment
}}
InputLabelProps={{
shrink: true
}}
autoComplete="off"
disabled={disabled}
/>
I wish I could do such a thing using Autocomplete of material ui: wertarbyte
That is, inserting text (string) without having a list of elements from which you must select.
Therefore the noOptions message should not appear, every time the enter key is pressed on the keyboard the text is inserted.
Link: codesandbox
Code:
import React from "react";
import Chip from "#material-ui/core/Chip";
import Autocomplete from "#material-ui/lab/Autocomplete";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const useStyles = makeStyles(theme => ({
root: {
width: 500,
"& > * + *": {
marginTop: theme.spacing(3)
}
}
}));
export default function Tags() {
const classes = useStyles();
return (
<div className={classes.root}>
<Autocomplete
multiple
id="tags-outlined"
options={[]}
defaultValue={["foo", "bar"]}
//getOptionLabel={(option) => option}
//defaultValue={[top100Films[13]]}
//filterSelectedOptions
renderInput={params => (
<TextField
{...params}
variant="outlined"
label="filterSelectedOptions"
placeholder="Favorites"
/>
)}
/>
</div>
);
}
In case you have simple elements (not objects, just strings), and you don't really need to handle state (your autocomplete is not controlled) you can use the freeSolo prop of the Autocomplete.
<Autocomplete
multiple
freeSolo
id="tags-outlined"
options={["foo", "bar"]}
defaultValue={["foo", "bar"]}
renderInput={params => (
<TextField
{...params}
variant="outlined"
label="filterSelectedOptions"
placeholder="Favorites"
/>
)}
/>
In case your elements are more complex and you do need to control the element:
Make sure the Autocomplete tag is a controlled one (you manage to value).
Listen to key down event on the TextField.
If the code is Enter (e.code === 'Enter') - take the value of the input and push it to the list of the current values that you have.
Make sure you also handle the onChange to handle the removal of elements:
Here is the code:
const [autoCompleteValue, setAutoCompleteValue] = useState(["foo", "bar"]);
return (
<Autocomplete
multiple
id="tags-outlined"
options={[]}
value={autoCompleteValue}
onChange={(e, newval, reason) => {
setAutoCompleteValue(newval);
}}
renderInput={params => (
<TextField
{...params}
variant="outlined"
label="filterSelectedOptions"
placeholder="Favorites"
onKeyDown={e => {
if (e.code === 'enter' && e.target.value) {
setAutoCompleteValue(autoCompleteValue.concat(e.target.value));
}
}}
/>
)}
/>
);
Check the live working example of both options: https://codesandbox.io/s/mui-autocomplete-create-options-on-enter-gw1jc
For anyone who wants to input the current best match on enter key press (as opposed to any custom text) you can use the autoHighlight prop.
<Autocomplete
multiple
autoHighlight
id="tags-outlined"
options={["foo", "bar"]}
defaultValue={["foo", "bar"]}
renderInput={params => (
<TextField
{...params}
variant="outlined"
label="filterSelectedOptions"
placeholder="Favorites"
/>
)}
/>
To do this, don't use the Autocomplete element from MUI. Just use a a standard TextField with the use of InputProps. All you need to do is add a onKeyDown listener to the TextField that listens for 'Enter' and when the function is triggered, have it add to an array of Chips in the InputProps. It might look something like this:
const [inputValue, setInputValue] = useState('');
const [chips, setChips] = useState([])
const inputChange = ({target: {value}}) => {setInputValue(value)};
const handleKeyDown = ({key}) => {
if(key === 'Enter') {
setChips([...chips, inputValue])
}
};
<TextField
fullWidth
variant="outlined"
label="Fish and Chips"
value={inputValue}
onChange={inputChange}
multiline
InputProps={{
startAdornment: chips.map((item) => (
<Chip
key={item}
label={item}
/>
)),
}}
/>
This is untested as written here, but it should work. I've done something similar in one of my apps.
Could you please tell why my required check is not working in autocomplete .I am using material UI with react hook form.
Step to reproduce
Click Submit button it show field is required.
then select any element from list.
remove the selected element Then click again submit button.It should
show “required” field check.but it is not showing anything why ??
Here is my code
https://codesandbox.io/s/mui-autocomplete-with-react-hook-form-0wvpq
<Controller
as={
<Autocomplete
id="country-select-demo"
multiple
style={{ width: 300 }}
options={countries}
classes={{
option: classes.option
}}
autoHighlight
getOptionLabel={option => option.label}
renderOption={(option, { selected }) => (
<React.Fragment>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option.label} ({option.code}) +{option.phone}
</React.Fragment>
)}
renderInput={params => (
<TextField
{...params}
label="Choose a country"
variant="outlined"
fullWidth
name="country"
inputRef={register({ required: true })}
// required
error={errors["country"] ? true : false}
inputProps={{
...params.inputProps,
autoComplete: "disabled" // disable autocomplete and autofill
}}
/>
)}
/>
}
onChange={([event, data]) => {
return data;
}}
name="country"
control={control}
/>
When the form loads initially, the value of your form is an empty object -
{}
When you select a country (say, 'Andorra') the value of your form becomes:
{"country":[{"code":"AD","label":"Andorra","phone":"376"}]}
And then when you deselect the country, the value of your form becomes:
{"country":[]}
An empty array technically meets the "required" criteria (it's not null, after all) so your required handler doesn't fire.
You can verify this is happening by showing the value of the form in your App class -
const { control, handleSubmit, errors, register, getValues } = useForm({});
return (
<form noValidate onSubmit={handleSubmit(data => console.log(data))}>
<Countries control={control} errors={errors} register={register} />
<Button variant="contained" color="primary" type="submit">
Submit
</Button>
<code>{JSON.stringify(getValues())}</code>
</form>
);
The simple fix is to NOT return an empty array as a value from your control - update your onChange handler as follows -
onChange={([event, data]) => {
return data && data.length ? data : undefined;
}}
I am referring to the documentation of React Material-UI (https://material-ui.com/components/autocomplete/).
In the demo code,
<Autocomplete
options={top100Films}
getOptionLabel={(option: FilmOptionType) => option.title}
style={{ width: 300 }}
renderInput={params => (
<TextField {...params} label="Combo box" variant="outlined" fullWidth />
)}
/>
I get how it works, but I am not sure how I am supposed to get the selected value.
For example, I want to use the onChange prop to this so that I can make some actions based on the selection.
I tried adding onChange={v => console.log(v)}
but the v does not show anything related to the selected value.
Solved by using passing in the (event, value) to the onChange props.
<Autocomplete
onChange={(event, value) => console.log(value)} // prints the selected value
renderInput={params => (
<TextField {...params} label="Label" variant="outlined" fullWidth />
)}
/>
The onChange prop works for multiple autocomplete values as well (#Steve Angello #ShwetaJ). The value returned is a list of all the selected options.
const [selectedOptions, setSelectedOptions] = useState([]);
const handleChange = (event, value) => setSelectedOptions(value);
const handleSubmit = () => console.log(selectedOptions);
.
.
.
<Autocomplete
multiple
autoHighlight
id="tags-outlined"
options={top100Films}
getOptionLabel={(option) => option.title}
onChange={handleChange}
filterSelectedOptions
renderInput={(params) => (
<TextField
{...params}
variant="standard"
/>
)}
/>
.
.
.
<button onClick={handleSubmit}>Submit!</button>
You can use useState to store the recevied value and onChange to get the value:
const [selected, setSelected] = useState([]);
return (
<Autocomplete
onChange={(event, value) => setSelected(value)}
renderInput={(params) => <TextField {...params} label="selected" />}
/>
);
Here is TS working example
const tags = ["perimeter", "Algebra", "equation", "square root"];
const handleInput = (e: React.SyntheticEvent, value: string[]) => {
console.log(value);
};
<Autocomplete
multiple
options={tags}
onChange={handleInput}
renderTags={(value: readonly string[], getTagProps) =>
value.map((option: string, index: number) => (
<Chip
variant="outlined"
label={option}
{...getTagProps({ index })}
/>
))
}
renderInput={(params) => (
<TextField
{...params}
variant="filled"
label="Tags"
placeholder="select question tags"
/>
)}
/>
============ Output ===============