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
})
)});
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;
Live Example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With