question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Change `formErrors` to produce normalized, deep object instead of `flatten()`

See original GitHub issue

I use error.formErrors in every project, and it’s used the default Blitz.js form abstraction for displaying form errors on the client.

The problem is that this flattens the errors to a single level, loosing critical path information for nested object errors.

You can see an example here:

const test = zod
  .object({
    name: zod
      .object({
        firstName: zod.string().nonempty({ message: "First name can not be empty." }),
        middleName: zod.string(),
        lastName: zod.string(),
      })
  })
  .safeParse({
    name: {
      firstName: "",
      middleName: "estrada",
      lastName: "",
    },a
  }).error.fieldErrors;
  {
    name: ["First Name can not be empty.", "Required", "Required"]
  }

Instead of the above, which is unusable, the result should be:

  {
    name: {
      firstName: ["First Name can not be empty."], 
      middleName: ["Required"],
      lastName: ["Required"]
  }

Workaround for 2 levels

  } catch (error) {
    const fieldErrors: any = {}
    for (const issue of error.issues) {
      if (issue.path.length > 0) {
        if (issue.path.length === 1) {
          fieldErrors[issue.path[0]] ??= []
          fieldErrors[issue.path[0]].push(issue.message)
        } else {
          fieldErrors[issue.path[0]] ??= {}
          fieldErrors[issue.path[0]][issue.path[1]] ??= []
          fieldErrors[issue.path[0]][issue.path[1]].push(issue.message)
        }
      } else {
        // form error
      }
    }
    return fieldErrors
  }

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:10
  • Comments:10 (6 by maintainers)

github_iconTop GitHub Comments

3reactions
lukeramsdencommented, Dec 11, 2020

This is currently the function I’m using to validate a large, nested form, with arrays of items, using Formik to handle form state:

import * as z from 'zod';
import {get, set} from 'lodash';
import {FormikErrors} from 'formik';

const formikValidateWithZod = <T extends z.Schema<any>>(
  validationSchema: T,
) => <F = z.infer<T>>(values: F): FormikErrors<F> => {
  const result = validationSchema.safeParse(values);

  if (result.success) {
    return {};
  } else {
    const fieldErrors: FormikErrors<F> = {};
    const processError = (e: z.ZodError) => {
      for (const error of e.errors) {
        if (error.code === 'invalid_union') {
          error.unionErrors.map(processError);
        } else {
          const path = error.path.map((x) => x.toString());
          const currentErrorAtPath = get(fieldErrors, path);
          set(
            fieldErrors,
            path,
            currentErrorAtPath // if error already exists, append as new line
              ? `${error.message}\n${currentErrorAtPath}`
              : error.message,
          );
        }
      }
    };
    processError(result.error);
    return fieldErrors;
  }
};

export default formikValidateWithZod;
2reactions
glennreyescommented, Feb 12, 2021

Here’s the workaround I am using to create the deep errors object for formik:

validationSchema.current?.safeParse(values)?.error?.errors?.reduce(
  (errors, error) =>
    error.path.reduce((a, b, level) => {
      if (level === error.path.length - 1) {
        a[b] = error.message;

        return errors;
      }

      if (!a[b]) {
        a[b] = {};
      }

      return a[b];
    }, errors),
  {} as { [key: string]: any },
);
Read more comments on GitHub >

github_iconTop Results From Across the Web

Flattening/normalizing deeply nested objects with unique keys
I tried setting the attributes (i.e. name, calories, ingredients, and serving_size) in the meta field and the dataframe looks similar to the ...
Read more >
Flatten, Reshape, and Squeeze Explained - Tensors for Deep ...
Flattening a tensor means to remove all of the dimensions except for one. The flatten() function takes in a tensor t as an...
Read more >
Flatten transformation in mapping data flow - Microsoft Learn
Denormalize hierarchical data using the flatten transformation in Azure Data Factory and Synapse Analytics pipelines.
Read more >
Flattening errors - Zod | Documentation
This is a special error code only thrown by a wrapped function returned by ZodFunction.implement() . The argumentsError property is another ZodError containing ......
Read more >
Flattened field type | Elasticsearch Guide [8.5] | Elastic
Flattened field typeedit. By default, each subfield in an object is mapped and indexed separately. If the names or types of the subfields...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found