Search code examples
javascriptreactjsyup

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


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.


Solution

  • 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.