Home > database >  Unable to get helper text to work properly with Yup validation and masking in MUI TextField with Rea
Unable to get helper text to work properly with Yup validation and masking in MUI TextField with Rea

Time:12-26

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

validator npm package

it has a function isMobilePhone()

  • Related