Search code examples
javascriptreactjsreact-hook-formyup

Yup validation based on value of another select field


I have two select inputs pickUpTime and dropOffTime in react-hook-form populated with an array of strings. The array intervalTime is an ordered time slots with a 15 minutes interval

const IntervalTime = [
    '09:00',
    '09:15',
    '09:30',
     ...
]

I want to add an error if dropOffTime is before pickUpTime and I thought of comparing the indexes of the selected time slots to do so

 resolver: yupResolver(yup.object({
            pickUpTime: yup.string().required(t('required')),
            dropOffTime: yup.string().when(['pickUpTime', 'dropOffTime'], {
                is: (pickUpTime, dropOffTime) =>
                    IntervalTime.indexOf(dropOffTime) < IntervalTime.indexOf(pickUpTime),
                then: yup.string().required('Drop off time must be after pick up time'),
            }),
        }))

but I get Error: Cyclic dependency, node was:"dropOffTime"


Solution

  • I solved it like this:

    resolver: yupResolver(yup.object({
                pickUpDate: yup.date().required(t('required')),
                pickUpTime: yup.string().required(t('required')),
                dropOffDate: yup.date().min(yup.ref('pickUpDate'), t('date-before')).required(t('required')),
                dropOffTime: yup.string().test('time', 'Drop off time must be after pick up time', function (value) {
                    const { pickUpTime, pickUpDate, dropOffDate } = this.parent;
                    if (!pickUpTime || !pickUpDate || !dropOffDate || !value) return true; // skip validation if any field is empty
                    return (dropOffDate > pickUpDate) || (dayjs(dropOffDate).date() === dayjs(pickUpDate).date() && dayjs(dropOffDate).month() === dayjs(pickUpDate).month() && IntervalTime.indexOf(value) >= IntervalTime.indexOf(pickUpTime));
                }).required(t('required')),
            }))
    

    I added a bit of validation to check if dropOffDate is after pickUpDate. In that case there's no need to check time as well.