Open kavlih opened 9 months ago
You can use the $
symbol by passing a context object on the validate()
function call.
Using your first example:
const schema = yup.object({
additionals: yup.object({
car: yup
.string()
.when(["$name"], ([name], schema) =>
name === "Pete"
? schema.required("required")
: schema.optional().nullable()
),
}),
name: yup.string().optional().nullable(),
});
schema.validate(myDataToValidate, { context: myDataToValidate });
If you have nested data you can use dot notation, e.g. $additionals.car
.
I don't want to change what Context is being sent for validation (Formik is handling that), so I'm working around this issue by adding a yup.test()
at the end of the schema, like this:
const schema = yup.object({
additionals: yup.object({
car: yup.string().nullable()
}),
name: yup.string().optional().nullable(),
}).test({
name: 'peteNeedsACar',
message: 'A car is required for Pete',
test: (value) => value.name !== 'Pete' || value.additionals.car.length !== 0,
});
Edit: This works in unit tests on the schema, but Formik seems to be ignoring it. I haven't yet figured out why.
Edit 2: My current code for this is throwing a ValidationError
instead of returning true/false -- but I also had a null-vs-emptystring issue that was throwing exceptions in the UI, so I'm not sure if the exception was required.
I don't plan to check if going from ValidationError back to true/false would work, because the ValidationError is what's telling Formik which field has a problem.
I'm trying to reference a field outside the current yup object. In this example,
car
should only be required whenname==='Pete'
. I found that thewhen
function in Yup only has access to the current level of the schema. And because thename
field is outside theadditionals
object, referencingname
in thewhen
function wont work.I read that "The $ symbol is used by Yup to reference fields from the root level of the schema." so i tried the same schema but using the
$
, which didn't workI got it solved with putting the
when
function on the object level and using two seperate schemas for both cases:But this solution is not very pretty and brings other problems with it. If i have other fields in the
additionals
object, i have to declare them in both schemas, even tho they might not be a part of the condition and i get a duplicated code. Also if i want to step through my form object (the type is based on the Yup schema) likeadditionals.car
i get the TypeScript ErrorTS2339: Property car does not exist on type {}
. So this solution wont really work for me.I tried to make a test case with the provided example. Not quite sure how it works and if i set it up correctly, but any feedback is welcomed: Codesandbox
Any help is appreciated.