RRR uzumaki
RRR uzumaki

Reputation: 1328

Formik scroll to the first invalid section after clicking on submit button

I am using Formik in my react project, I have implemented all the validations with yup and succesfully showing the errors. One thing i want is if user clicks on submit button i want to scroll it to the section which has validation errors in it.

I tried a way but couldnt achieve it here is the code below but it gives me error

document.getElementsByName(Object.keys(formik.errors)[0])[0].focus() is undefined

but if the first div passes validation and error is on input box it works fine

  const mortgageData = [
    "Estou a obter um crédito habitação",
    "Quero comparar com o seguro que tenho ",
    "O meu seguro renova em breve",
  ];

  const formik = useFormik({
    initialValues: {
      insuranceMotive: null,
      creditCapital: null,
    },
    onSubmit: (values) => {
      console.log(values);
    },
    validationSchema: validationSchemaSectionOne, //schema which validates the input with the help of Yup
  });

  useEffect(() => {
    // this is the code which i tried but the problem is my first
    // field is not input, its a <CheckTable/> component which
    // is a div that has text in it, so this code scrolls to input
    // box and ignores the first div, even it has errors
    if (!formik.isSubmitting) return;
    if (Object.keys(formik.errors).length > 0) {
      document.getElementsByName(Object.keys(formik.errors)[0])[0].focus();
    }
  }, [formik]);

  return (
    <div className="firstSection">
      <form onSubmit={formik.handleSubmit}>
        <p className="tab-text">
          Porque estás á procura de um Seguro Vida Crédito Habitação?
        </p>
        <div className="selectable-tags-mortgage">
          {mortgageData.map((tag, index) => (
            <CheckableTag
              tag={tag}
              key={index}
              setValue={(val) => formik.setFieldValue("insuranceMotive", val)}
              value={formik.values.insuranceMotive}
            />
          ))}
        </div>
        {formik.errors.insuranceMotive && formik.touched.insuranceMotive && (
          <div className="formik-errors">{formik.errors.insuranceMotive}</div>
        )}

        <p className="tab-text">Qual o capital em € a cobrir pelo seguro? </p>
        <Input
          size="large"
          name="creditCapital"
          className="input-credit-capital"
          value={formik.values.creditCapital}
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
        />
        {formik.errors.creditCapital && formik.touched.creditCapital && (
          <div className="formik-errors">{formik.errors.creditCapital}</div>
        )}

        <button type="submit" className="button-enabled">
          CONTINUAR
        </button>
      </form>
    </div>
  );
}

CheckableTag component

export default function CheckableAntTag({ tag, value, setValue }) {
  const { CheckableTag } = Tag
 

  return (
    <CheckableTag
      style={{
        backgroundColor: tag === value ? '#AACECD' : 'white'
      }}
      className="selectable-ant-tags"
      key={tag}
      checked={tag === value}
      onChange={() => setValue(tag)}>
      {tag}
    </CheckableTag>
  )
} 

So if insuranceMotive is null, its an error as i have added required to that field, the error message gets logged successfully but i want to scroll to the CheckableTag section instead of input

Upvotes: 0

Views: 2716

Answers (1)

Markus
Markus

Reputation: 2061

Instead of using

Object.keys(formik.errors)[0])[0].focus()

you should use

Object.keys(formik.errors)[0])[0].scrollIntoView({ block: 'center'})
Object.keys(formik.errors)[0])[0].focus({ preventScroll: true})

Upvotes: 1

Related Questions