Reputation: 73
I have 2 dropdowns in each row and I can dynamically add and remove rows apart form the first one. I would like to submit form if there is only one row (rendered from the beginning) and it is empty and not be able to submit if:
or
I am using yup validation.
I have tried with checking the length with .test(), but this test run always after checking 'required'.
This is what I would like to have:
const validationSchema = yup.object({
values:
yup.array()
.of(
yup.object({
value1: yup.string().required(), // ONLY IF ARRAY LENGTH > 1
value2: yup.string().required()// ONLY IF VALUE1 IS SELECTED
})
)});
Upvotes: 4
Views: 7059
Reputation: 3723
If I understand you correctly, then this should do.
const mySchema = yup.object({
values: yup.array().of(
yup.object({
value1: yup
.string()
.test(
"test-1",
"error: required if array length > 1",
(value, context) => {
const [, values] = context.from;
const {
value: { values: arrayValues }
} = values;
// ONLY IF ARRAY LENGTH > 1
if (arrayValues.length > 1) {
// valid only if value is provided
return !!value;
}
}
),
value2: yup.string().when("value1", {
// if value1 is provied, value2 should be provided too
is: (value1) => !!value1,
then: (value2) => value2.required()
})
})
)
});
// should pass
console.log(
mySchema.validateSync({
values: [
{ value1: "1", value2: "2" },
{ value1: "1", value2: "2" }
]
})
);
// ValidationError: error: required if array length > 1
console.log(
mySchema.validateSync({
values: [{ value1: "1", value2: "2" }, { value2: "2" }]
})
);
// ValidationError: values[1].value2 is a required field
console.log(
mySchema.validateSync({
values: [{ value1: "1", value2: "2" }, { value1: "1" }]
})
);
The key thing here is to remove .required()
and provide your own check in test()
when the array meets your custom condition.
to access the parent value inside of .test()
, use context.from
const [parent1, parent2, ...rest] = context.from;
Upvotes: 4