Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle multiple errors returned by Yup #1864

Open
KrzysztofMadejski opened this issue Oct 8, 2019 · 5 comments
Open

Handle multiple errors returned by Yup #1864

KrzysztofMadejski opened this issue Oct 8, 2019 · 5 comments

Comments

@KrzysztofMadejski
Copy link

馃殌 Feature request

When Yup returns a ValidationError aggregating multiple errors I'd like Formik to list all aggregated errors.

Current Behavior

Currently if Yup returns ValidationError then its message is shown.

Desired Behavior

With following validation:

clinicalFiles: Yup.array()
      .min(10, 'We expect you to provide 10 files')
      .max(10, 'We expect you to provide 10 files')
      .test('valid-domains', 'Domains are invalid', function (value: File[]) {
        let errors = validateFileNames(value.map(f => f.name));

        if (errors.length > 0) {
          let ve = this.createError({ message: 'Error that is shown' });
          ve.errors = errors; // these are not shown
          return ve;
        }

        return true;
      })

I'd expect Formik to show all aggregated errors.

Suggested Solution

If ValidationError ve packs other errors then show all of them, instead of just ve.message

Who does this impact? Who is this for?

Ppl using Yup validations (which are recommended by Formik)

Describe alternatives you've considered

Concatenating all errors:

      Yup.array().test('valid-domains', 'Domains are invalid', function (value: File[]) {
        let errors = validateFileNames(value.map(f => f.name));

        if (errors.length > 0) {
          return this.createError({ message: errors.join(". ") });
        }

        return true;
      })
@stale stale bot added the stale label Dec 7, 2019
@jazithedev
Copy link

Is there any progress in regards to this topic? I assume, that Formik still can't process multiple errors for a single field?

@stale stale bot removed the stale label Jun 13, 2020
@dieguezz
Copy link

You can do it programmatically. Instead of using validationSchema use validate and the validateFunction should look something like this:

export function validateSchema(values, schema) {
  return schema
    .validate(values, {
      abortEarly: false,
      strict: false,
    })
    .then((res) => {
      return {}
    })
    .catch(mapYupToFormikErrors)
}

and do something like

validateSchema(values, schema)

@LyricL-Gitster
Copy link

LyricL-Gitster commented Jan 18, 2021

Expanding on @dieguezz, this will give you a full validate method for a schema until such time that we can pass schema options to Formik:

const fullValidatorForSchema = (schema) => (values) => schema.validate(values, {
  abortEarly: false,
  strict: false,
}).then(() => ({})).catch(({inner}) => inner.reduce((memo, {path, message}) => ({
  ...memo,
  [path]: (memo[path] || []).concat(message),
}), {}))

So you can:

<Formik validate={fullValidatorForSchema(YupValidationSchema)} {...otherProps} />

And, then your Formik errors will be an array of all of the error messages.

@dieguezz
Copy link

dieguezz commented Jan 19, 2021

Expanding on @dieguezz, this will give you a full validate method for a schema until such time that we can pass schema options to Formik:

const fullValidatorForSchema = (schema) => (values) => schema.validate(values, {
  abortEarly: false,
  strict: false,
}).then(() => ({})).catch(({inner}) => inner.reduce((memo, {path, message}) => ({
  ...memo,
  [path]: (memo[path] || []).concat(message),
}), {}))

So you can:

<Formik validate={fullValidatorForSchema(YupValidationSchema)} {...otherProps} />

And, then your Formik errors will be an array of all of the error messages.

I forgot to share my original mapYupToFormikErrors so it has the same shape than formik errors and you can avoid more customization further on


export function mapYupToFormikErrors(err: { inner: any[] }) {
  return err.inner
    .filter((i: { message: any }) => !!i.message)
    .reduce(
      (curr: any, next: { path: any; errors: any[] }) => ({
        ...curr,
        [next.path]: next.errors[0],
      }),
      {},
    )
}

@AndresPope
Copy link

the problem was solved? i need the same thing for my app, i need to show several error messages

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants