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}
/>
)}
/>
)}
/>
Related
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)}
/>
)}
/>
);
}
I have a Mui Autocomplete Component with a react-hook-form Controller.
When I set the freeSolo attribute the value doesn't get reset. When I call for example: resetField("selBinvrk") without freeSolo everything works as expected. Here is the code for my autocomplete and the submit function. Can anybody help me with that problem?
<Controller
name={name}
control={control}
rules={rules}
render={({ field: { onChange, value } }) => (
<Autocomplete
disabled={!disabled ? false : true}
value={value}
freeSolo={freeSolo}
//autoSelect={autoSelect}
options={options}
getOptionLabel={getOptionLabel}
isOptionEqualToValue={isOptionEqualToValue}
/* getOptionSelected={(option, value) => {
console.log('get option selected: ', option, value);
return value === undefined || value === "" || option.ID === value.ID}
} */
//console.log(item);
onChange={(event, item) => {
//console.log(item);
onChange(item);
}}
//renderOption={renderOption}
renderInput={(params) => (
<TextField
{...params}
label={label}
variant="outlined"
error={isError}
helperText={errorMessage}
sx={sx}
inputRef={inputRef}
/>
)}
/>
)}
/>
const onSubmit = (data, e) => {
console.log("hä: ", e);
resetField("selBinvrk");
resetField("selMenge");
mutate({
binv_id: data.selBinv.ID,
bsa_id: data.selBinvrk?.BSA_ID || 0,
binvrk_id: data.selBinvrk?.ID || 0,
selMenge: data.selMenge,
bsm_id: data.selBsm.ID,
});
//recaptchaRef.current.execute();
//mutate(data);
};
I have a mui autocomplete component. I am trying to reuse this autocomplete component with a form where formik validation added.
My autocomplete component is,
const CustomAutoCompleteField = props => {
const {rerenderAutocomplete, data, refetchCategoryData, autoCompleteFieldsData, inputLabel, autoCompleteFieldsInputOnChange , onTouch, onErrors,fieldProps, onBlur} = props
const [textFieldData, setTextFieldData] = useState(null)
const onChangeHandler = (event, value) =>{
}
return (
<>
<Autocomplete
key={rerenderAutocomplete}
// value={onEdit && data}
isOptionEqualToValue={(option, value) => option.name === value.name}
onBlur={onBlur}
onChange={onChangeHandler}
fullWidth
id="tags-outlined"
options={autoCompleteFieldsData ? autoCompleteFieldsData : top100Films }
getOptionLabel={(option) => option.name}
filterSelectedOptions
renderInput={(params) => (<TextField
required
{...params}
label={inputLabel}
onChange={textFieldInputOnChange}
error={Boolean(onTouch && onErrors)}
helperText={onTouch && onErrors}
{...fieldProps}
/>)}
/>
</>
);
};
Here I am passing formik attributes in side props which are, onTouch, onErrors,fieldProps, onBlur.
In My Parent component, i am using this autocomplete field by giving props, which are,
<CustomAutoCompleteField inputLabel='Select Category'
onBlur={addNewServiceFormik.handleBlur}
onTouch={addNewServiceFormik.touched.selectedCategoryName}
onErrors={addNewServiceFormik.errors.selectedCategoryName}
fieldProps={addNewServiceFormik.getFieldProps('selectedCategoryName')}
/>
I don,t know why, when i click submit on my form, this autocomplete doesn't show any helper text as per formik validation.
I simply created a component for this
In the form your must pass FormikProvider for use with FormikContext
import { TextField } from '#mui/material';
import Autocomplete from '#mui/material/Autocomplete';
import { useFormikContext } from 'formik';
import React from 'react';
type OptionsValues = {
title: string,
value: string
}
type Props = {
id: string,
name: string,
label: string,
options: OptionsValues[]
}
function MuiltSelect(props: Props) {
const { options, name, label, id } = props
const formik = useFormikContext();
return (
<Autocomplete
{...props}
multiple
options={options}
getOptionLabel={(option: any) => option.title}
onChange={(_, value) => formik.setFieldValue(name, value)}
filterSelectedOptions
isOptionEqualToValue={(item: any, current: any) => item.value === current.value}
renderInput={(params) => (
<TextField
{...params}
id={id}
name={name}
label={label}
variant={"outlined"}
onChange={formik.handleChange}
error={formik.touched[name] && Boolean(formik.errors[name])}
helperText={formik.errors[name]}
value={formik.values[name]}
fullWidth
/>
)
}
/>
)
}
export default MuiltSelect
check gist
https://gist.github.com/Wellers0n/d5dffb1263ae0fed5046e45c47a7c4a7
In react native I want to make a dynamic controller component. But i cant access errors with it. I using "react-hook-form" for form elements. So Its my component :
const {
control,
handleSubmit,
formState: {errors},
setValue,
} = useForm();
const DynamicController = ({req, pattern, name, label}) => {
return (
<>
<Text style={[t.textBase]}>{label}</Text>
<Controller
control={control}
defaultValue=""
rules={{
required: {
value: true,
message: 'Bu alan boş bırakılamaz!',
},
}}
render={({field: {onChange, onBlur, value}}) => (
<Input
errorText={errors[name].message}
error={errors[name]}
onBlur={onBlur}
placeholder={label}
onChangeText={onChange}
value={value}
/>
)}
name={name}
/>
</>
);
};
My Input Component is basicly simple input. My problem is when i give error name like that example i cant access errors.
Its how i use my component :
<DynamicController
label="Email"
name="Email"
pattern={true}
req={true}
/>
When i dont fill the element and log the submit its not showing any error. Its simple passing validate. So what can i do where do i make wrong ? thank you for answerings!!!
Is your Input a custom wrapper? If not, a better way do this using react-hook-form would be:
const {
control,
handleSubmit,
formState: {errors},
setValue,
} = useForm(
defaultValues: {
firstName: '', // form fields should be populated here so that the error can be displayed appropriately
lastName: ''
}
);
const DynamicController = ({req, pattern, name, label}) => {
return (
<>
<Text style={[t.textBase]}>{label}</Text>
<Controller
control={control}
defaultValue=""
rules={{
required: {
value: true,
message: 'Bu alan boş bırakılamaz!',
},
}}
render={({field: {onChange, onBlur, value}}) => (
<Input
onBlur={onBlur}
placeholder={label}
onChangeText={onChange}
value={value}
/>
)}
name={name}
/>
{errors[name] && <Text>This is required.</Text>}
</>
);
};
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}
/>