Validate phone number with Yup?
Asked Answered
O

11

81

I'm trying to validate a phone number with Yup:

phone: Yup.number()
  .typeError("That doesn't look like a phone number")
  .positive("A phone number can't start with a minus")
  .integer("A phone number can't include a decimal point")
  .min(8)
  .required('A phone number is required'),

.min(8) validates that the number is 8 or more. So simply entering 8 will pass. How can I make 8 characters required so 1000 0000 would pass?

Obtund answered 24/9, 2018 at 16:4 Comment(0)
P
153

Hi right now I'am solving same problem as you and I found possible solution.

Validate phone number with string that matches Regex

const phoneRegExp = /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/

phoneNumber: Yup.string().matches(phoneRegExp, 'Phone number is not valid')

You can search for different Regex Expressions and validate it. I've used Regex from this article https://www.sitepoint.com/community/t/phone-number-regular-expression-validation/2204

Premium answered 8/11, 2018 at 14:49 Comment(8)
matches(" ") is working for me, it is giving a warning as Possible Unhandled Promise Rejection (id: 0): TypeError: Cannot read property 'length' of undefined in react-native. Please help meThemistocles
Sirisha I think its because your variable is not a string. Initialise your variable as empty string and then listen to onChanged event in TextInput.Premium
why \\? worked for me only after removing redundant escapes.Female
/^((\+[1-9]{1,4}[ -]?)|(\([0-9]{2,3}\)[ -]?)|([0-9]{2,4})[ -]?)*?[0-9]{3,4}[ -]?[0-9]{3,4}$/ worked best for me. @Premium your expression matches thing such as +32----------1111111Liddell
@Liddell I tried your regex -- but this allowed numbers with multiple + in the middle +32+232232232Waftage
codesandbox.io/s/…Waftage
LGenzelis - codesandbox.io/s/…Waftage
Flipflop -- codesandbox.io/s/…Waftage
R
56

>. Update .<

http://yup-phone.js.org/

I've created a yup-phone module that uses google-libphonenumber which gives accurate validation checks and can be installed directly from github

npm install --save yup yup-phone.

Check Usage

const Yup = require('yup');
require('yup-phone');

// validate any phone number (defaults to India for country)
const phoneSchema = Yup.string().phone().required();
phoneSchema.isValid('9876543210'); // → true


From Simple React Validator,

The regex for phone number validation is

/^(\+?\d{0,4})?\s?-?\s?(\(?\d{3}\)?)\s?-?\s?(\(?\d{3}\)?)\s?-?\s?(\(?\d{4}\)?)?$/

Example

// index.js

const yup = require('yup');
const { rePhoneNumber } = require('./yup-phone')

const schema = yup.string().phone()

const phone = '+911234567890';
console.log('Is Valid? ', rePhoneNumber.test(phone)); // Is Valid? true
schema.validateSync(phone);

// yup-phone.js

const yup = require('yup');

const rePhoneNumber = /^(\+?\d{0,4})?\s?-?\s?(\(?\d{3}\)?)\s?-?\s?(\(?\d{3}\)?)\s?-?\s?(\(?\d{4}\)?)?$/;

module.exports.rePhoneNumber = rePhoneNumber

yup.addMethod(yup.string, "phone", function() {
  return this.test("phone", "Phone number is not valid", value =>
    rePhoneNumber.test(value)
  );
});

Ropedancer answered 26/4, 2019 at 10:53 Comment(4)
unless I've missed something along the way, I have not been able to pass validation for a blank field. That is, I only want to validate if a value is present.Mistake
I originally gave this an upvote. However, the bundle size is larger than my entire website. Do not use it on the frontendElam
I tried to use yup-phone here -- codesandbox.io/s/yup-phone-validation-forked-ixgnjj -- but it will allow numbers with ++ at the front? -- "++33343335678"Waftage
even google-lib phone allowed this -- codesandbox.io/s/google-phone-lib-demo-forked-k29kk8 "+++33343335678"Waftage
T
12

Try this, it might be helpful for you.

mobile: Yup.string().matches(/^[6-9]\d{9}$/, {message: "Please enter valid number.", excludeEmptyString: false})
Themistocles answered 4/1, 2019 at 6:29 Comment(3)
it wouldn't validate phone numbers starting with digits 1-5Poacher
yes @RahilAhmad, usually in India mobile numbers starts with either 6 or 7 or 8 or 9, so regex validates those numbers only.Themistocles
It allows number starting with 0Brander
D
12

const phoneRegExp = /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/


phone_number: Yup.string()
  .required("required")
  .matches(phoneRegExp, 'Phone number is not valid')
  .min(10, "too short")
  .max(10, "too long"),

This works best for me...you can set your own length...i just wanted 10 digits not less or more

Delmadelmar answered 8/8, 2020 at 16:0 Comment(0)
L
4

Just a little collaboration. On my case I don't want to validate if the input is empty (when is not required). Thank you all for your examples!

yup.addMethod(yup.string, "phone", function(messageError = 'Phone number is not valid') {
    const phoneRegExp = /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/
    return this.test('phone', messageError, value => {
      if (value && value.length > 0) {
        return phoneRegExp.test(value)
      }
      return true
    })
})
Linzy answered 4/3, 2020 at 20:46 Comment(1)
I'm doing something similar with .transform(). Is it more appropriate to use .test()?Haskins
T
2

I made a new package for this called yup-phone-lite. I had used the original yup-phone package but it uses the massive google-libphonenumber so I replaced it with a smaller fork.

Topmast answered 4/6, 2021 at 1:45 Comment(0)
U
1

I have a similar use case, and here's my solution:

// Regex source: https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s02.html

const phoneRegex = RegExp(
  /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/
);

const schema = yup.object().shape({
  phone: yup.string().matches(phoneRegex, "Invalid phone").required("Phone is required")
});
Urbane answered 27/5, 2020 at 9:1 Comment(0)
O
1

Here's a snippet from my code.

let schema = yup.object().shape({
  phone: yup
    .string()
    // regexr.com/6anqd
    .matches(/(\+91\ )[6-9]{1}[0-9 ]{4}[0-9 ]{4}[0-9]{3}/, {
      message: "Invalid Indian number",
      excludeEmptyString: false,
    })
    .required(),
  email: yup.string().required().email(),
  password: yup.string().required().min(8),
  confirmPassword: yup
    .string()
    .required()
    .oneOf([yup.ref("password")], "Passwords do not match"),
  agree: yup
    .boolean()
    .oneOf(
      [true],
      "It is essential to accept our Privacy Policy to register.",
    ),
});

My regex checks for Indian Phone numbers following the format, +91 axxx xxx xxx (where a can be a digit in the range 6 to 9 and x can be 0 - 9).

I tried yup-home but it was not able to actually verify the range for the Indian Number I wanted, plus, the package import size was costly.


Also, I'm using React with Formik at the frontend for form validation with react-phone-input-2

<PhoneInput
  country={"in"}
  value={values.phone}
  name="phone"
  onChange={(phone, data, e) => handleChange(e)}
  onBlur={(e) => handleBlur(e)}
  defaultMask=".... ... ..."
  masks={{ in: ".... ... ..." }}
  onlyCountries={["in"]}
  inputProps={{
    name: "phone",
    required: true,
    autoFocus: true,
  }}
  disableSearchIcon={true}
  disableDropdown={true}
  containerClass="mt-1 border h-12 text-sm focus:outline-none block w-full bg-gray-100 dark:bg-transparent border-transparent focus:bg-white"
  inputClass="mt-1 border h-12 text-sm focus:outline-none block w-full bg-gray-100 dark:bg-transparent border-transparent focus:bg-white"
  inputStyle={{
    background: "transparent",
    border: "1px solid grey",
    height: "3em",
    width: "100%",
    outline: "none",
  }}
  buttonStyle={{
    height: "3em",
    background: "transparent",
    outline: "none",
    border: "none",
  }}
/>
{handleFormikError(errors, touched, "phone")} // returns the span.alert with error message
Obeded answered 2/12, 2021 at 10:7 Comment(0)
D
0

Here is how I combined yup with other 3rd phone validation libraries ("awesome-phonenumber" in my case):

import { parsePhoneNumber } from "awesome-phonenumber";
import * as Yup from "yup";

const schema = Yup.object().shape({
  name: Yup.string().required("Required"),
  phoneNumber: Yup.string()
    .required("Required")
    .test("phoneNumber", "Phone number is not valid", (str, context) => {
      const pn = parsePhoneNumber(str);
      return pn.valid;
    }),
  addressLine1: Yup.string().required("Required"),
  // ...Other fields
});
Discriminate answered 19/7, 2023 at 9:37 Comment(0)
T
0

Hi, This is regex for indian local mobile number validation and for Indian international .

starting with 9,8,7 you can add more as well.

you can test it using https://regex101.com/

import * as Yup from "yup";

const phoneNumberRules = /^(?:(?:\+|0{0,2})91(\s*[\-]\s*)?|[0]?)?[789]\d{9}$/;

const emailRules = /^[a-zA-Z0-9._%+-]+@(gmail|yahoo)\.com$/;

export const clientSchema=Yup.object().shape({

    name:Yup.string().required("Name Not be Empty"),

    email: Yup.string().email("Invalid Email!")
      .matches(emailRules, { message: " Not valid :{" })
      .required("Email Required !"),

      phone: Yup.string()
      .matches(phoneNumberRules, { message: "Invalid Phone Number!" })
      .required("Phone Number Required !"),
})
Tilly answered 18/8, 2023 at 5:15 Comment(0)
S
0

In my case, phone number is an optional field and I didn't want to care about a complex pattern. So I used the test method with a simple regex

yup.string().test('phone', `Invalid phone number`, (v) => {
  if (!v) {
    return true;
  }
  return /^\+?\d{6,15}$/.test(v);
});
  • accept "+" symbol
  • min 6 digits
  • max 15 digits
Sassenach answered 20/9, 2023 at 13:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.