2
votes

I have a dynamic form using Formik's <Form /> and <FieldArray /> components. I have the validation schema like so:

const countPerKgSchema = total => {
  return Yup.object().shape({
    rows: Yup.array()
      .of(
        Yup.object().shape({
          count: Yup.string().required('Count is required'),
          kg: Yup.string().required('Weight is required.'),
        })
      )
      .required()
      .min(1, `Provide at least 1 row`),
    saleIds: Yup.array()
      .of(Yup.number)
      .required(),
  });
};

How can I add a validation rule that the sum of all counts in the rows array must match total?

1

1 Answers

2
votes

You just need to use Yup's test() method to validate the total:

object().shape({
  rows: array()
    .of(...)
    .required()
    .test(
      'sum',
      'The total number of elements must match the total.',
      (rows = []) => {
        const total = rows.reduce((total, row) => {
          return total + (row.count|| 0);
        }, 0);

        return total <= XYZ;
      }
    )
})

If that validation fails, the errors object will look like this:

{
  "rows": {
    "message": "The total number of elements must match the total.",
    "type": "sum"
  }
}

You can then display the error with { errors.rows?.message }.