Why required check not working after removing element? - javascript

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;
}}

Related

Checking checkbox inside Autocompletion with MUI

[
{ label: 'First', checked: false },
{ label: 'Second', checked: true }
]
Here is a very short snippet of how the data could look like.
I am using Material UI's Autocomplete, to make it possible for searching on labels.
These labels are having a checkbox.
Problem is, I can't use onChange on <Checkbox /> when its a renderOption
The Autocomplete just closes, without doing any action
<Autocomplete
disableCloseOnSelect={true}
options={array}
getOptionLabel={option => option.label.toString()}
renderInput={params => (
<TextField
{...params}
fullWidth
label="Select label"
variant="outlined"
error={false}
/>
)}
renderOption={opt => (
<div>
<Checkbox
checked={opt.checked}
onChange={() => alert('not being fired...')}
/>
<p>{opt.label}</p>
</div>
)}
/>
You shouldn't use onChange in Checkbox, You should use onChange prop of Autocomplete, and set default value by value prop
and Checkbox receive its props from renderOption's props
const [selectedOptions, setSelectedOptions] = useState([]);
useEffect(() => {
setSelectedOptions(options.filter(op => op.checked));
}, []);
<Autocomplete
options={options}
value={selectedOptions}
onChange={(event, newValue) => {
setSelectedUsers(newValue);
}
renderOption={(props, option, { selected }) => (
<div {...props}>
<Checkbox checked={selected} />
<p>{option.name}</p>
</div>
)}
disableCloseOnSelect
/>
onChange event will work in Checkbox provided in renderOption function but it only works when you click on checkbox not anywhere else on list item. You can use onClick on the parent div if that fulfills your purpose.

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"
/>
);
}}
/>

Material UI Autocomplete component won't clear input when Informed state is reset

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}
/>

How to reset Autocomplete in react-hook-forms?

I'm working with react-hook-forms and trying to reset all form fields after submit. The problem is that in my case Autocomplete accepts objects as a value.
I've tried to set the defaultValue to {}, but received the following message:
Material-UI: the getOptionLabel method of Autocomplete returned undefined instead of a string for
{}
Are there any variants how Autocomplete could be reset?
Here is a link to the CodeSandbox
A little late to the party but here's a solution if anyone else needs it.
Assuming your autocomplete is wrapped inside a Controller, all you have to do is explicitly check the value in Autocomplete. Refer below for more
<Controller
name="category"
control={control}
rules={{ required: true }}
render={({ field }) => (
<Autocomplete
fullWidth
options={categories}
{...field}
// =====================================================
// Define value in here
value={
typeof field.value === "string"
? categories.find((cat) => cat === field.value)
: field.value || null
}
// =====================================================
onChange={(event, value) => {
field.onChange(value);
}}
renderInput={(params) => (
<TextField
{...params}
label={t("product_category")}
error={Boolean(errors.productCategory)}
helperText={errors.productCategory && "Product Category is required!"}
/>
)}
/>
)}
/>
This should do the trick!
To reset the value of AutoComplete with reset of react hook form you should add the value prop to the AutoComplete, other ways the reset wont function, see the example:
import { useEffect, useState } from 'react'
import {
Autocomplete,
TextField,
reset,
} from '#mui/material'
...
const {
...
setValue,
control,
formState: { errors },
} = useForm()
useEffect(() => {
reset({
...
country: dataEdit?.country ? JSON.parse(dataEdit?.country) : null,
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dataEdit])
...
<Controller
control={control}
name="country"
rules={{
required: 'Veuillez choisir une réponse',
}}
render={({ field: { onChange, value } }) => (
<Autocomplete
value={value || null}
options={countries}
getOptionLabel={(option) => option.name}
onChange={(event, values) => {
onChange(values)
setSelectedCountry(values)
setValue('region', null)
}}
renderInput={(params) => (
<TextField
{...params}
label="Pays"
placeholder="Pays"
helperText={errors.country?.message}
error={!!errors.country}
/>
)}
/>
)}
/>

Material-UI Autocomplete & TextField triggers google autocomplete

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" />
}}
/>

Categories