I am trying to implement masking in an @mui/material
TextField with react-hook-form
but having trouble with the helper text to function properly. It works fine with all the other TextField inputs.
Expected behavior:
When the user clicks on submit and Yup
validates the form with specified schema, the helper text shows error messages for invalid input data. The error message automatically disappears afterwards when the user types proper input value which gets validated as the user types.
Problem statement: This is working for the email field, but not for the masked cell phone TextField. The error message never actually disappears and the value does not get validated once the helper text appears and the error gets generated for the first time after an on submit event is invoked.
Here's the Yup Schema:
const Schema = Yup.object().shape({
email: Yup.string().required("Email is required").email(),
cellPhone: Yup.number()
.min(10, "Cell phone must have 10 digits at least")
.max(12, "Cell phone must have 12 digits at max")
.required("Cell phone is required")
.typeError("Cell phone is required")
});
I tried two approaches. The first approach includes a custom component which I created using react-input-mask
for masking and Controller from react-hook-form
for a controlled MUI TextField:
<Controller
name="cellPhone"
control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<InputMask mask=" 99-999-9999999" value={value} onChange={onChange}>
{(inputProps) => (
<TextField
{...inputProps}
fullWidth
label="Cell phone"
error={!!error}
helperText={error?.message}
/>
)}
</InputMask>
)}
/>;
The second approach included an MUI-based component available on npm, called material-ui-phone-number
:
<Controller
name="cellPhone"
control={control}
render={({ name, onBlur, onChange, value, fieldState: { error } }) => (
<MuiPhoneNumber
name={name}
value={value}
onBlur={onBlur}
onChange={onChange}
defaultCountry={"us"}
style={{ width: "100%" }}
label="Cell phone"
variant="outlined"
margin="normal"
error={!!error}
helperText={error?.message}
/>
)}
/>;
I got the same result from both approaches and haven't been able to find the correct answer or to generate the expected outcome. Any help in resolving this is much appreciated, thanks a bunch!
I made a codesandbox for it.
CodePudding user response:
This works with your first approach.
Have your yup schema as
const Schema = Yup.object().shape({
email: Yup.string().required("Email is required").email(),
cellPhone: Yup.string()
.required("Cell phone is required")
.matches(
/^(\ \d{1,2}-)?\(?\d{3}\)?[-]\d{7}$/,
"Cell phone must have 12 digits at max"
)
});
Since you have masked data and - symbols will be in your value. So cellPhone is not a number field according to Yup. You can see this if you remove .typeError() in your schema,
So, using regexp you can validate your phone number.
CodePudding user response:
For your second approach, do the changes below
<Controller
name="cellPhone"
control={control}
render={({
field,
fieldState: { error }
}) => (
<MuiPhoneNumber
{...field}
onChange={(value,{name,countryCode,dialCode},...rest)=>{
console.log("onchange",value,name,countryCode,dialCode)
field.onChange(value)
}}
defaultCountry={"us"}
style={{ width: "100%" }}
label="Cell phone"
variant="outlined"
margin="normal"
error={!!error}
helperText={error?.message}
/>
)}
/>
Yup schema would be,
const Schema = Yup.object().shape({
email: Yup.string().required("Email is required").email(),
cellPhone: Yup.string()
.required("Cell phone is required")
.test('isValidMobile', 'Error message', (val) => {
console.log("yup value",val)
//do your validation - return false to show error
return true;
})
});
for validating you can use this npm package
it has a function isMobilePhone()