Yup: Deep Validation in Array of Objects

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?

6 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();
    });
  }}
/>;
3

Base on @olefrank'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')), // <– `.min(1)` instead of `.required()`
  taskSchedules: Yup.array(),
});

I have done this type of validation in my Node.js(Express.js) project. You can try validation in this way.

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()
    })
  )
})

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

In my case I have used formik with yup for this,

I want to select only one value in an array if not selected I need to display the error

array =  [{"label": "Option 1", "selected": false, "value": "option-1"}, {"label": "Option 2", "selected": false, "value": "option-2"}, {"label": "Option 3", "selected": false, "value": "option-3"}]

Yup.mixed().test({
 message: 'Required',test: 
val => val.filter(i => i.selected === true).length === 1})

it worked for me

Yup.mixed().test({
 message: 'Required',test: 
val => val.filter(i => i.selected === true).length !== 0})
1

I did a similar validation like this. You can try this approach

const schema = yup.object().shape({
    subject: yup.string().required(),
    description: yup.string()
    daysOfWeek: yup.array().of(
      yup.lazy(value => {
        const { checked } = value // Get the value of checked field

        return checked
          ? yup.object().shape({
              dayOfWeek: yup.string().required(), // validate only if checked is true
              checked: yup.boolean()
            }) 
           : yup.object().shape({
              dayOfWeek: yup.string(),
              checked: yup.boolean()
            })
      })
    ),
    taskSchedules: yup.array()
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Robert Thorne

Robert Thorne

Automotive & Future Transportation Editor

Robert Thorne covers electric vehicle innovations, autonomous driving systems, global mobility trends, and automotive engineering developments.

Share this article
Twitter Facebook Pinterest