Tab Focuses endIcon instead of next field in Material UI TextField - reactjs

Im using functional components and react hook forms with material ui
When resetting a password pressing tab i want to focus the next field instead of the endIcon.
i have tried using useRef but its not working.
Here is my code
<Controller
name="new_password"
control={control}
render={({ field }) => (
<TextField
{...field}
className="mt-8 mb-16"
type="password"
label="New Password"
error={!!errors.new_password}
helperText={errors?.new_password?.message}
variant="outlined"
fullWidth
required
onKeyUp={e => {
console.log('key pressed');
if (e.key === 'Tab') {
console.log('tab pressed');
confirmPassword.current.focus();
}
}}
autoComplete="off"
InputProps={{
className: 'pr-2',
type: showPassword ? 'text' : 'password',
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={() => setShowPassword(!showPassword)}>
<Icon className="text-20" color="action">
{showPassword ? 'visibility' : 'visibility_off'}
</Icon>
</IconButton>
</InputAdornment>
)
}}
/>
)}
/>
<Controller
name="confirm_password"
control={control}
render={({ field }) => (
<TextField
{...field}
className="mt-8 mb-16"
type="password"
id="confirm_password"
label="Confirm Password"
error={!!errors.confirm_password}
helperText={errors?.confirm_password?.message}
variant="outlined"
ref={confirmPassword}
fullWidth
required
autoComplete="off"
InputProps={{
className: 'pr-2',
type: showConfirmPassword ? 'text' : 'password',
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={() => setShowConfirmPassword(!showConfirmPassword)}>
<Icon className="text-20" color="action">
{showConfirmPassword ? 'visibility' : 'visibility_off'}
</Icon>
</IconButton>
</InputAdornment>
)
}}
/>
)}
/>
i did try using ref but its not working. is there a way around to achieve this.

Related

Password field showing "password is required" even after a value is passed

I am working on a login form with Next Js as frontend and uses MUI 5. The issue is that even after i pass a value to password field, when i click on login button it is showing password field is required. Also when i try to console log the username and password to test it, only username got displayed in the console. please help me to understand what mistake I am doing. Please find the login form below
Please find the code MUI code for both username and password(I am making use of a purchased theme)
<form noValidate autoComplete='off' onSubmit={handleSubmit}>
<FormControl fullWidth sx={{ mb: 4 }}>
<Controller
name='Username'
control={control}
rules={{ required: true }}
render={({ field: { value, onChange, onBlur } }) => (
<TextField
autoFocus
label='Username'
value={value}
onBlur={onBlur}
//onChange={onChange}
onChange={(e)=> setUsername(e.target.value)}
error={Boolean(errors.user)}
// placeholder='admin#materio.com'
/>
)}
/>
{errors.user && <FormHelperText sx={{ color: 'error.main' }}>{errors.user.message}</FormHelperText>}
</FormControl>
<FormControl fullWidth>
<InputLabel htmlFor='auth-login-v2-password' error={Boolean(errors.password)}>
Password
</InputLabel>
<Controller
name='password'
control={control}
rules={{ required: true }}
render={({ field: { value, onBlur } }) => (
<OutlinedInput
value={value}
onBlur={onBlur}
label='Password'
//onChange={onChange}
onChange={(e)=> setPassword(e.target.value)}
id='auth-login-v2-password'
error={Boolean(errors.password)}
type={showPassword ? 'text' : 'password'}
endAdornment={
<InputAdornment position='end'>
<IconButton
edge='end'
onMouseDown={e => e.preventDefault()}
onClick={() => setShowPassword(!showPassword)}
>
{showPassword ? <EyeOutline /> : <EyeOffOutline />}
</IconButton>
</InputAdornment>
}
/>
)}
/>
{errors.password && (
<FormHelperText sx={{ color: 'error.main' }} id=''>
{errors.password.message}
</FormHelperText>
)}
</FormControl>

Passing an array to textfield

I have this response back from the backend, and apparently it's a collection of objects,
"deductions": [
{
"id": 3,
"receiptId": 3,
"type": "loan",
"amount": 200,
"reason": "You have took a loan...",
"createdAt": "2022-02-28T13:16:38.219Z",
"updatedAt": "2022-02-28T13:16:38.219Z",
"deletedAt": null
}
]
And I have three fields contained within the "Deduction" array and I used "TextField" as shown in the code
But the problem is that "deduction" is an array, I didn't know how to pass it to display all of them on the screen
<tbody>
<tr>
<td>
<Controller
name="deductions.amount"
control={control}
render={({ field }) => (
<TextField
{...field}
className="mt-8 mb-16"
// error={!!errors.salary.amount}
required
// helperText={errors?.salary.amount?.message}
// label="amount"
autoFocus
id="deductions.amount"
variant="outlined"
fullWidth
InputProps={{
startAdornment: (
<InputAdornment position="start">£</InputAdornment>
),
}}
/>
)}
/>
</td>
<td>
<Controller
name="deductions.type"
control={control}
render={({ field }) => (
<TextField
{...field}
className="mt-8 mb-16"
// error={!!errors.salary.bonus}
required
// helperText={errors?.salary.bonus?.message}
// label="Type"
autoFocus
id="deductions.type"
variant="outlined"
fullWidth
/>
)}
/>
</td>
<td>
<span className="truncate">
{" "}
<Controller
name="deductions.reason"
control={control}
render={({ field }) => (
<TextField
{...field}
className="mt-8 mb-16"
// error={!!errors.salary.workStartDate}
required
// helperText={errors?.salary.workStartDate?.message}
// label="Reason"
autoFocus
id="deductions.reason"
variant="outlined"
fullWidth
/>
)}
/>
</span>
</td>
</tr>
</tbody>
I tried to use the map, but it failed
how can i solve the problem?
{order.deductions.map((deduction) => (
<tr key={deduction.id}>
<td>
<Controller
name="deductions.amount"
control={control}
render={({ field }) => (
<TextField
{...field}
className="mt-8 mb-16"
// error={!!errors.salary.amount}
required
// helperText={errors?.salary.amount?.message}
// label="amount"
autoFocus
id="deductions.amount"
variant="outlined"
fullWidth
InputProps={{
startAdornment: (
<InputAdornment position="start">
£
</InputAdornment>
),
}}
/>
)}
/>
</td>
<td>
<Controller
name="deductions.type"
control={control}
render={({ field }) => (
<TextField
{...field}
className="mt-8 mb-16"
// error={!!errors.salary.bonus}
required
// helperText={errors?.salary.bonus?.message}
// label="Type"
autoFocus
id="deductions.type"
variant="outlined"
fullWidth
/>
)}
/>
</td>
<td>
<span className="truncate">
{" "}
<Controller
name="deductions.reason"
control={control}
render={({ field }) => (
<TextField
{...field}
className="mt-8 mb-16"
// error={!!errors.salary.workStartDate}
required
// helperText={errors?.salary.workStartDate?.message}
// label="Reason"
autoFocus
id="deductions.reason"
variant="outlined"
fullWidth
/>
)}
/>
</span>
</td>
</tr>
))}
i hope you want to set response data to the input fields, so you can do as shown below
{order?.deductions.map((deduction, index) => (
<tr key={deduction.id}>
<td>
<Controller
name={deduction.amount}
control={control}
render={({ field }) => (
<TextField
{...field}
value={deduction.amount}
className="mt-8 mb-16"
// error={!!errors.salary.amount}
required
// helperText={errors?.salary.amount?.message}
// label="amount"
autoFocus
id={deduction.amount}
variant="outlined"
fullWidth
InputProps={{
startAdornment: (
<InputAdornment position="start">
£
</InputAdornment>
),
}}
/>
)}
/>
</td>
<td>
<Controller
name={deduction.type}
control={control}
render={({ field }) => (
<TextField
{...field}
value={deduction.type}
className="mt-8 mb-16"
// error={!!errors.salary.bonus}
required
// helperText={errors?.salary.bonus?.message}
// label="Type"
autoFocus
id={deduction.type}
variant="outlined"
fullWidth
/>
)}
/>
</td>
<td>
<span className="truncate">
{" "}
<Controller
name={deduction.reason}
control={control}
render={({ field }) => (
<TextField
{...field}
value={deduction.reason}
className="mt-8 mb-16"
// error={!!errors.salary.workStartDate}
required
// helperText={errors?.salary.workStartDate?.message}
// label="Reason"
autoFocus
id={deduction.reason}
variant="outlined"
fullWidth
/>
)}
/>
</span>
</td>
</tr>
))}

Error: input is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML` using with meterial ui

i got this error while working with mui on react anyone can answer this
i want to create password feild with show and hide functions
<FormControl variant="filled">
<InputLabel htmlFor="conpassword">
confrom password
</InputLabel>
<FilledInput
id="conpassword"
type={passShow ? "text" : "password"}
value={formValues.conpassword}
onChange={handelChange}
onBlur={_onBlur}
error={errors.conpassword ? true : false}
endAdornment={
<InputAdornment position="end">
<IconButton
onClick={(e) => {
e.preventDefault();
setPassShow(!passShow);
}}
edge="end"
>
{passShow ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
}
/>
<span className="helper">{errors.conpassword}</span>
</FormControl>

setValue not working for react hookform with select

I am using react hook form. setValue is not working with select.I tried both in controller and in function but that doesnt work.Below is my code.
<Controller
name="mealkit"
control={control}
register={register}
defaultValue="Ready to eat"
setValue={selectedRow.mealkit}
rules={{ required: true, minLength: 4 }}
render={({ field }) => (
<Select
defaultValue="Ready to eat"
setValue={selectedRow.mealkit}
variant="outlined"
fullWidth
id="mealkit"
label="Mealkit"
inputProps={{ type: 'mealkit' }}
error={Boolean(errors.mealkit)}
helperText={
errors.mealkit
? errors.mealkit.type === "minLength"
? "mealkit should have atleast 4 letters"
: "mealkit is required"
: ""
}
{...field}
>
<MenuItem value={'Ready to eat'}>Ready to eat</MenuItem>
<MenuItem value={'Ready to cook'}>Ready to cook</MenuItem>
<MenuItem value={'Heat and eat'}>Heat and eat</MenuItem>
</Select>
)}
/>

react-hook-form material-ui (FormControlLabel + Checkbox) using Controller

to use Material-ui in react-hook-form you should use <Controller and the method render instead of "as = {xy-control}" Also should not mix controller and inputRef = {register}.
A single control is also no problem.
But there is a compound control in Material-ui. "FormControlLabel + CheckBox" how do you integrate this control in the controller. All my attempts have failed.
This is how it works but I would like the FormControlLaben to be enclosed by the controller.
Does somebody has any idea?
<Controller
name="password"
control={control}
defaultValue={""}
render={(props) => <TextField {...props}
variant="outlined"
margin="normal"
required
fullWidth
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>}
/>
<FormControlLabel
control={
<Checkbox
inputRef={register}
name="remember"
/>
}
label="remember"
/>
{/*That works, but it requires an OnChange. Why can't the controller bind it?*/}
<FormControlLabel
control={
<Controller
name={"remember2"}
control={control}
render={(props) => (
<Checkbox
{...props}
onChange={(e) => props.onChange(e.target.checked)}
/>
)}
/>
}
label="remember"
/>
Here's how I did it
<FormControlLabel
control={
<Controller
control={control}
inputRef={register}
name='controlName'
render={({onChange, value}) => (
<Checkbox
onChange={e => onChange(e.target.checked)}
checked={value}
/>
)}
/>
}
label="This is a label"
/>
From v7, I used this :
<Controller
name='contactAutre'
control={control}
defaultValue={false}
render={({ field }) => (
<FormControlLabel
control={<Checkbox {...field} />}
label='Autre'
/>
)}
/>
this was enough for me w/ Mui 5 & RHF 7
const { watch, register } = useForm<{saveEmail: boolean}>({
defaultValues: { saveEmail: true },
});
...
<FormControlLabel
control={
<Checkbox {...register('saveEmail')} checked={watch('saveEmail')} />
}
label="save email"
/>
Credit to Leo Roese for his example for Textfield. However you can apply the same logic for Checkboxes but slightly tweak.
const { control, formState: { errors } } = useForm()
<Controller
name="privacyAccept"
control={control}
render={({ field }) => (
<>
<FormControlLabel
control={<Checkbox {...field} />}
label="I agree to the privacy policy"
/>
{errors.privacyAccept && (
<FormHelperText error>{errors.privacyAccept.message}</FormHelperText>
)}
</>
)}
/>
Another way to make things more controlled:
<FormControlLabel
label="label here"
control={
<Controller
name="isSeparatedDelivery"
control={control}
render={({ field: { onChange, value } }) => (
<Checkbox
checked={value}
onChange={(e) => onChange(e.target.checked)}
/>
)}
/>
}
/>
or
<Controller
control={control}
name="selected"
render={({ field: { onChange, value } }) => (
<FormControlLabel
control={
<Checkbox
label="Sélectionner la question"
checked={value}
onChange={onChange}
/>
}
label="Sélectionner la question"
/>
)}
/>

Resources