Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yup: deep validation in array of objects

Tags:

yup

formik

I have a data structure like this:

{
  "subject": "Ah yeah",
  "description": "Jeg siger...",
  "daysOfWeek": [
    {
      "dayOfWeek": "MONDAY",
      "checked": false
    },
    {
      "dayOfWeek": "TUESDAY",
      "checked": false
    },
    {
      "dayOfWeek": "WEDNESDAY",
      "checked": true
    },
    {
      "dayOfWeek": "THURSDAY",
      "checked": false
    },
    {
      "dayOfWeek": "FRIDAY",
      "checked": false
    },
    {
      "dayOfWeek": "SATURDAY",
      "checked": true
    },
    {
      "dayOfWeek": "SUNDAY",
      "checked": true
    }
  ],
  "uuid": "da8f56a2-625f-400d-800d-c975bead0cff",
  "taskSchedules": [],
  "isInitial": false,
  "hasChanged": false
}

In daysOfWeek I want to ensure that at least one of the items has checked: true.

This is my validation schema so far (but not working):

const taskValidationSchema = Yup.object().shape({
  subject: Yup.string().required('Required'),
  description: Yup.string(),
  daysOfWeek: Yup.array()
    .of(
      Yup.object().shape({
        dayOfWeek: Yup.string(),
        checked: Yup.boolean(),
      })
    )
    .required('Required'),
  taskSchedules: Yup.array(),
})

Is it possible to validate the values of daysOfWeek ensuring that at least one of them has checked: true?

like image 269
olefrank Avatar asked Dec 05 '19 14:12

olefrank


4 Answers

I solved it using compact() (filtering out falsely values) together with setTimeout after the FieldArray modifier function:

const validationSchema = Yup.object().shape({
  subject: Yup.string().required(i18n.t('required-field')),
  description: Yup.string(),
  daysOfWeek: Yup.array()
    .of(
      Yup.object().shape({
        dayOfWeek: Yup.string(),
        checked: Yup.boolean(),
      })
    )
    .compact((v) => !v.checked)
    .required(i18n.t('required-field')),
  taskSchedules: Yup.array(),
});

And in form:

<Checkbox
  value={day.dayOfWeek}
  checked={day.checked}
  onChange={(e) => {
    replace(idx, { ...day, checked: !day.checked });
    setTimeout(() => {
      validateForm();
    });
  }}
/>;
like image 95
olefrank Avatar answered Sep 30 '22 20:09

olefrank


Base on Mario Petrovic's answer. This code work with me.

const validationSchema = Yup.object().shape({
  subject: Yup.string().required(i18n.t('required-field')),
  description: Yup.string(),
  daysOfWeek: Yup.array()
    .of(
      Yup.object().shape({
        dayOfWeek: Yup.string(),
        checked: Yup.boolean(),
      })
    )
    .compact((v) => !v.checked)
    .min(1, i18n.t('required-field')),
  taskSchedules: Yup.array(),
});
like image 35
Duy Nguyen Avatar answered Sep 30 '22 21:09

Duy Nguyen


**I have done this type of validation in my Node.js(Express.js) project. It works fine for me. You can try validation in this way. Hopefully it will work for you also. **

const validationSchema = yup.object({
subject: yup.string().required(),
description: yup.string().required(), 
daysOfWeek: yup.array(
    yup.object({
        dayOfWeek: yup.string().required(),
        checked: yup.boolean().required()
    })
)

})

like image 43
MD. SHIFULLAH Avatar answered Sep 30 '22 21:09

MD. SHIFULLAH


If you trying in latest version it should be used like this Yup.array().min(1, "At least one option is required").required()

like image 37
Ravindra Avatar answered Sep 30 '22 21:09

Ravindra