Yup: Validate list of emails

Created on 1 Jul 2019  路  8Comments  路  Source: jquense/yup

How to validate a list of emails like [email protected];[email protected]

I tried to convert the string to an array and validate each email like this, but it's difficult to mix strings and arrays:
yup.array().transform((str) => str.split(';')).of(yup.string().email()).required()

Most helpful comment

This solution transforms a comma delimited string into an array of emails and then performs email validation on each one.

const validationSchema = Yup.object().shape({
  email: Yup.array()
    .transform(function(value, originalValue) {
      if (this.isType(value) && value !== null) {
        return value;
      }
      return originalValue ? originalValue.split(/[\s,]+/) : [];
    })
    .of(Yup.string().email(({ value }) => `${value} is not a valid email`)),
});

All 8 comments

what's wrong with your example? Does it not work?

It is applied on a text input containing: [email protected];[email protected]. Since that is a String and not an Array, the transform receives a null

The original value actually has this data, so this works without the required
yup.array().transform((str) => str.split(';')).of(yup.string().email()).required()

With required, I'm getting Cannot read property 'length' of undefined probably because it's reading the value and not originalValue

probably because it's reading the value and not originalValue

O right, yes you should use originalValue here, since value will be null or empty b/c the built in array parsing will have failed

I'm getting a similar issue where my initial value starts off as an array, but as soon as I type something the entire value becomes a string and no string validations are performed

I had to do this recently and ended up with the following. Maybe it'll help someone else?

const isEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value); // or use your own
const EmailFormValidationSchema = object().shape({
  body: string().required(),
  recipient: string()
    .transform((value) => Array.from(new Set(value.split(';'))).join(';')) // dedupe - optional step
    .required()
    .test(
      'emails',
      'Invalid email address',
      (value) => value && value.split(';').every(isEmail)
    ),
  subject: string().required(),
});

This solution transforms a comma delimited string into an array of emails and then performs email validation on each one.

const validationSchema = Yup.object().shape({
  email: Yup.array()
    .transform(function(value, originalValue) {
      if (this.isType(value) && value !== null) {
        return value;
      }
      return originalValue ? originalValue.split(/[\s,]+/) : [];
    })
    .of(Yup.string().email(({ value }) => `${value} is not a valid email`)),
});

If this is useful to anybody:

const isEmailSchema = Yup.string().email();
const schema = Yup.object().shape({
  "email-list": yup
    .string()
    .required("This field cannot be empty")
    .test({
      name: "emails",
      test: function(value) {
        const firstInvalidEmail = value
          .split(",")
          .map(email => email.trim())
          .filter(v => !isEmpty(v))
          .find(v => !isEmailSchema.isValidSync(v));

        return !firstInvalidEmail
          ? true
          : this.createError({
              message: `The email address '${firstInvalidEmail}' is invalid.`
            });
      }
    })
});
Was this page helpful?
0 / 5 - 0 ratings