reectrix
reectrix

Reputation: 8629

Validation using Yup to check string or number length

Is there a yup function that validates a specific length?

I tried .min(5) and .max(5), but I want something that ensures the number is exactly 5 characters (ie, zip code).

Upvotes: 108

Views: 256301

Answers (17)

Abhith Shaji
Abhith Shaji

Reputation: 647

You can convert the number to a string and check its length.

Yup.number()
.required("Required")
.test("min-length", "Please enter a valid number", (value) => {
  // Convert the number to a string and check its length
  const stringValue = String(value);
  return stringValue.length == 10;
}),

Upvotes: 0

louisgz_
louisgz_

Reputation: 1

You can use typeError like following:

yup.number()
    .typeError('Must be only digits')
    .test('len', 'Must be exactly 5 characters', val => val.length === 5)

Upvotes: 0

Evaldas
Evaldas

Reputation: 206

i convert my number to string and store my number in a react state as a string.

my solution was this

    amount: Yup.number()
      .test('len', maxAmountLength, () => amountState.length <= 50)

Upvotes: 0

S. Hesam
S. Hesam

Reputation: 6643

This is a simple solution, but it is not perfect.

Yup.string()
.required()
.min(5, 'Must be exactly 5 digits')
.max(5, 'Must be exactly 5 digits')

One of the solutions is:

Yup.string().matches(/^[0-9]{5}$/, 'Must be exactly 5 digits')

Upvotes: -4

Lina Caetano
Lina Caetano

Reputation: 11

matches(/^[0-9]{8}$/, "Only 8 digits") Now, the Yup will show error if the user input letter and more or less 8 digits

Upvotes: 1

Brayan Loayza
Brayan Loayza

Reputation: 698

Works like a charm for type number.

yup.number().test('len', 'Max 6 numbers', (val) => val.toString().length <= 6)

Upvotes: 9

Free Palestine
Free Palestine

Reputation: 975

You can also still use the validation for number but when using test for validation of length you will have convert it to a string before testing it.

Yup.object().shape({
  zipCode: Yup.number()
    .required('Zip code is a required field')// optional
    .typeError('Zip code can only be a number')// optional as well
    .test('len', 'Zip code needs to be excatly 5 digits', val => val.toString().length === 5)
});

Upvotes: 3

Harshal
Harshal

Reputation: 8310

Try this:

Yup.number()
.required()
.min(10000, 'Must be exactly 5 characters')
.max(99999, 'Must be exactly 5 characters')
.label("Zip Code"),

Upvotes: 5

Siddharth Jain
Siddharth Jain

Reputation: 880

import { string, date} from 'yup' // Take out what is needed in import

string()
.trim()
.matches(
  /^[0-9]{4}[0-9]{2}[0-9]{2}T 0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}Z$/,
  'createdOn is not in correct format',
)
.max(24),

Upvotes: 0

David Ferreira
David Ferreira

Reputation: 1766

You can also use string.length.

yup.string().length(5)

But it doesn't work with numbers starting with zeros:

const yup = require('yup')

const schema = yup.string().length(5)

console.log(schema.isValidSync(12345)) // (true) This is valid.
console.log(schema.isValidSync(00123)) // (false) This is NOT valid.

Upvotes: 30

BoyePanthera
BoyePanthera

Reputation: 614

The test API runs into issues with ReactJs when your field has no value. You can use the length API instead

Yup.string().length(4, 'This field has to be exactly 4 characters!')

Upvotes: 3

SimoAmi
SimoAmi

Reputation: 1996

This check leads to the best validation experience:

Yup.string()
.required()
.matches(/^[0-9]+$/, "Must be only digits")
.min(5, 'Must be exactly 5 digits')
.max(5, 'Must be exactly 5 digits')

output:

12f1    // Must be only digits
123     // Must be exactly 5 digits
123456  // Must be exactly 5 digits
01234   // valid
11106   // valid

Demo: https://codesandbox.io/s/yup-y6uph

Upvotes: 115

tschumann
tschumann

Reputation: 21

@efru's answer works great for numbers that are less than 22 characters. However val.toString().length does not work for numbers larger than 22 characters. The reason for this is that larger numbers are converted to exponential format when converted to a string in javascript.

The solution I found that works best is:

Yup.number().test('len', 'Must be exactly 25 characters', val => Math.ceil(Math.log10(val + 1)) === 25)

Upvotes: 0

Matt Royal
Matt Royal

Reputation: 335

To add to the other answers, none of them are checking that a value exists (I see some have mentioned this in comments after posting this though)...

If it is not present and the field is left empty, it will be trying to get the length of undefined or null which will then give you a javascript error and prevent other conditions such as .required() from working (if you had it setup like of course).

This would probably be slightly better:

// Check we have a value as well
Yup.number().test('len', 'Must be exactly 5 characters', val => val && val.toString().length === 5 )

Upvotes: 6

dtesta
dtesta

Reputation: 171

@Tamlyn's answer covers the length validation aspect of the question quite well.

In the case of a zip code, you could use a regex to enforce the length and limit to numeral values within the Yup.string() (you wouldn't want to use a Yup.number() type as it wouldn't support zip codes starting with a zero 0####)

// ##### format zip code
Yup.string().matches(/^[0-9]{5}$/, 'Must be exactly 5 digits')

// ##### and #####-#### format zip codes
Yup.string().matches(/^[0-9]{5}(?:-[0-9]{4})?$/, 'Must be 5 or 9 digits')

Upvotes: 17

ogie
ogie

Reputation: 1470

For future reference, if you're looking to validate a number (zip code), the above solution requires a slight tweak. The function should be :

Yup.number().test('len', 'Must be exactly 5 characters', val => val.toString().length === 5)

.length does not work on numbers, only strings.

Upvotes: 41

Tamlyn
Tamlyn

Reputation: 23564

I don't think there's anything built in but it's easy to implement with test:

yup.string()
  .test('len', 'Must be exactly 5 characters', val => val.length === 5)

https://runkit.com/tamlyn/5ad9b99a4ba1230012d7ac21

Upvotes: 92

Related Questions