Yup: How to require either one of two fields? (Cyclic dependency error)

Created on 20 Jan 2017  路  7Comments  路  Source: jquense/yup

What (if possible) is the correct way to define that either the email or phone is a string > 1?

    var formModelSchema = yup.object({
        email: yup.string().email().when('phone', {
            is: (phone) => !phone || phone.length === 0,
            then: yup.string().email().required(),
            otherwise: yup.string()
        }),
        phone: yup.string().when('email', {
            is: (email) => !email || email.length === 0,
            then: yup.string().required(),
            otherwise: yup.string()
        })
    });

Uncaught (in promise) Error: Cyclic dependency: "phone"

Most helpful comment

    var formModelSchema = yup.object({
        email: yup.string().email().when('phone', {
            is: (phone) => !phone || phone.length === 0,
            then: yup.string().email().required(),
            otherwise: yup.string()
        }),
        phone: yup.string().when('email', {
            is: (email) => !email || email.length === 0,
            then: yup.string().required(),
            otherwise: yup.string()
        })
    },
   // This is what you missed
   [ [ 'email', 'phone' ] ]
);

All 7 comments

Generally I move the validation up to the object. OR don't use when and write a custom test:

yup.string().test(function (value) {
  const { email } = this.parent;
  if (!email) return value != null
  return true
})

If you want to use when there is an escape hatch you can use, as documented in this test: https://github.com/jquense/yup/blob/master/test/object.js#L609

Correction to the [above] link:

https://github.com/jquense/yup/blob/master@{2017-01-20}/test/object.js#L609

Generally I move the validation up to the object. OR don't use when and write a custom test:

yup.string().test(function (value) => {
  const { email } = this.parent;
  if (!email) return value != null
  return true
})

If you want to use when there is an escape hatch you can use, as documented in this test: https://github.com/jquense/yup/blob/master/test/object.js#L609

You have a typo in the code. You are declaring a function and using an arrow afterwards. Corrected:

js yup.string().test(function (value) { const { email } = this.parent; if (!email) return value != null return true })

Generally I move the validation up to the object. OR don't use when and write a custom test:

yup.string().test(function (value) => {
  const { email } = this.parent;
  if (!email) return value != null
  return true
})

If you want to use when there is an escape hatch you can use, as documented in this test: https://github.com/jquense/yup/blob/master/test/object.js#L609

If you're wondering why this is not working, then make sure you're not using an arrow function for the callback
yup.string().test((value) => {.... won't work since this is undefined :)

    var formModelSchema = yup.object({
        email: yup.string().email().when('phone', {
            is: (phone) => !phone || phone.length === 0,
            then: yup.string().email().required(),
            otherwise: yup.string()
        }),
        phone: yup.string().when('email', {
            is: (email) => !email || email.length === 0,
            then: yup.string().required(),
            otherwise: yup.string()
        })
    },
   // This is what you missed
   [ [ 'email', 'phone' ] ]
);

I had to use yup.object().shape({...}) with @GeoffreyHervet solution to avoid cyclic dependency error.

    var formModelSchema = yup.object({
        email: yup.string().email().when('phone', {
            is: (phone) => !phone || phone.length === 0,
            then: yup.string().email().required(),
            otherwise: yup.string()
        }),
        phone: yup.string().when('email', {
            is: (email) => !email || email.length === 0,
            then: yup.string().required(),
            otherwise: yup.string()
        })
    },
   // This is what you missed
   [ [ 'email', 'phone' ] ]
);

error
var validationSchemaFilter = Yup.object().shape(
{
bookingTimeBegin: Yup.string().when('bookingTimeEnd', {
is: (bookingTimeEnd) => bookingTimeEnd?.length > 0,
then: Yup.string().required('Ch峄峮 ng脿y b岷痶 膽岷'),
otherwise: Yup.string(),
}),
bookingTimeEnd: Yup.string().when('bookingTimeBegin', {
is: (bookingTimeBegin) => bookingTimeBegin?.length > 0,
then: Yup.string().required('Ch峄峮 ng脿y k岷縯 th煤c'),
otherwise: Yup.string(),
}),
},
[['bookingTimeBegin', 'bookingTimeEnd']],
);

Was this page helpful?
0 / 5 - 0 ratings