Yup validation at lower level based on a higher value - unsure how to access

Viewed 27

Given the following Yup schema:

const myValSchema = Yup.object().shape({
  myGroups: Yup.array()
    .of(
      Yup.object().shape({
        myName: Yup.string()
          .required('Name is required')
        mySelection: Yup.number().required('Selection is required'),          
        myHobbies: Yup.array().of(
          Yup.object().shape({
            hobbyName: Yup.string()
              .required('Hobby name is required'),
            hobbyLikes: Yup.number()
              .nullable()
              .when("dummy", {
               is: (value) => 
               mySelection === 99,
                 then: Yup.number().typeError('Value must be a number').required('Likes is required').positive(),
              }),
          })
        )
      })
    )
});

I need to validate hobbyLikes only when the value of mySelection outside of this shape equals 99 but I am unsure how to access this outside value.

Just unsure how to achieve this.

1 Answers

There was a GitHub issue for this requirement, but currently, it is closed and it seems that there are only workaround solutions for this problem.

You can use this work-around solution by using context.options.from[1] by using custom test() instead of using when() to access a parent value:

const myValSchema = Yup.object().shape({
  myGroups: Yup.array().of(
    Yup.object().shape({
      myName: Yup.string().required("Name is required"),
      mySelection: Yup.number().required("Selection is required"),
      myHobbies: Yup.array().of(
        Yup.object().shape({
          hobbyName: Yup.string().required("Hobby name is required"),
          hobbyLikes: Yup.number()
            .nullable()
            .test("isSelection", "Likes is required", (value, context) => {
              const currentSelectionValue =
                context.options.from[1].value.mySelection;
              if (
                currentSelectionValue === "99" ||
                currentSelectionValue === 99
              ) {
                return value > 0;
              }
              return true;
            })
        })
      )
    })
  )
});

You can take a look at this sandbox for a live working example of this workaround solution.

Related