I'm using Formik with Yup and Typescript, and I have this as an initial value of the form ...
const initialValues = {
title: "",
overview: "",
related_items_id: [],
short_desc: ""
};
And here's my schema ...
const formSchema = Yup.object().shape({
title: Yup.string()
.trim()
.required("This field is required."),
overview: Yup.string().required("This field is required."),
related_items_id: Yup.array()
.min(1, "Pick at least 1 item")
.of(Yup.number().required("This field is required.")),
short_desc: Yup.string().required("This field is required.")
});
Now, I need either the related_items_id
array or the short_desc
to be required, if one is filled with data the other is not required and vise Versa, how can I accomplish that using something like when
in yup?
Here's a codesandbox I created to show the error that I'm getting when trying to use the when
method of Yup ...
https://codesandbox.io/s/formik-yup-required-one-or-the-other-nextjs-gujqv
For conditionally setting your formSchema, checkout the docs Conditionally Set Required Field (Yup).
const basicFormSchema = Yup.object().shape(
{
title: Yup.string()
.trim()
.required("This field is required."),
overview: Yup.string().required("This field is required."),
related_items_id: Yup.array().when("short_desc", {
is: "",
then: Yup.array()
.min(1, "Pick at least 1 item")
.of(Yup.number().required("This field is required.")),
otherwise: Yup.array()
}),
short_desc: Yup.string().when("related_items_id", {
is: relatedItemsId => relatedItemsId.length === 0,
then: Yup.string().required("This field is required."),
otherwise: Yup.string()
})
},
[["related_items_id", "short_desc"]]
);
You can achieve this by creating a type that is interdepedent on related_items_id
and short_desc
export interface BaseType {
title: string;
overview: string;
}
interface RelatedItemsType extends BaseType {
related_items_id?: Array<any>;
short_desc?: never;
}
interface ShortDescType extends BaseType {
related_items_id?: never;
short_desc?: string;
}
export type InitialValueType = RelatedItemsType | ShortDescType;
and you can make use of it like this
const initialValues: InitialValueType = {
title: "",
overview: "",
related_items_id: [],
// short_desc: "" no longer required
};