Reputation: 1396
I'm trying to write a yup validator that validates a field's max length, depending on whether a dash is included in the string. If a dash is included, the max length is 10, if there is no dash, the max length should be 9.
For example:
'string-111'
should have a max length of 10.
'string111'
should have a max length of 9.
My current code looks like:
import * as Yup from 'yup';
export default Yup.object().shape({
description: Yup.string()
.matches(
/^[a-zA-Z0-9-]*$/,
'Invoice # can only contain letters, numbers and dashes'
)
.max(10, 'Invoice # has a max length of 10 characters'),
});
I see the yup documentation https://github.com/jquense/yup has a .when()
method, but it seems to be used in very specific cases in their examples. Here, the user can place the dash anywhere in the string.
Any ideas on how to rewrite this validator, so that when there is no dash in the string, the maxlength should be 9?
Upvotes: 0
Views: 5853
Reputation: 110675
I worked up a solution I liked but found it had already been posted by @Thefourthbird, so I tried a different tack and came up with this:
/^(?=(?:-*[^-]-*){9}$)(?=(?:[^-]*-[^-]*){0,1}$).*/gm
You can see that this regex contains two positive lookaheads, both beginning at the start of a line. The first ensures that the string contains 9 non-hyphens; the second requires that there be at most one hyphen.
The demo provides a detailed and thorough explanation of how this regex works, but we can also make it self-documenting by writing it in free-spacing mode:
/
^ # match beginning of string
(?= # begin a positive lookahead
(?:-*[^-]-*){9} # match 9 strings, each with one char that is
# not a hyphen, possibly preceded and/or
# followed by hyphens
$ # match the end of a line
) # end positive lookahead
(?= # begin a positive lookahead
(?:[^-]*-[^-]*){0,1} # match 0 or 1 strings, each containing one hyphen,
# possibly preceded and/or followed by non-hyphens
$ # match the end of the string
) # end positive lookahead
.* # match 0+ characters (the entire string)
/gmx # global, multiline and free-spacing regex
# definition modes
If desired, [^-]
could replaced with [a-zA-Z0-9]
, \p{Alnum}
or something else, depending on requirements.
Upvotes: 1
Reputation: 163237
You could match either match 10 chars where a hyphen can occur at any place using a positive lookahad, or match 9 chars consisting only of a-z0-9.
^(?:(?=[a-z0-9-]{10}$)[a-z0-9]*-[a-z0-9]*|[a-z0-9]{9})$
Explanation
^
Start of string(?:
Non capture group
(?=
Positive lookahead, assert what is on the right is
[a-z0-9-]{10}$
Match 10 times either a-z0-9 or - till the end of the string)
Close lookahead[a-z0-9]*-[a-z0-9]*
Match a hyphen between chars a-z0-9|
Or[a-z0-9]{9}
Match 9 chars a-z0-9)
Close group$
End of stringUpvotes: 2