14

I'm trying to validate a password with the following regex:
^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.{8,}).
Note that there is no terminating $ char, because that would prevent valid passwords from being accepted. (I'm not sure why the input field doesn't terminate the string).
However, Angular's Validators.pattern adds the end of string char. And therefore my valid passwords fail.
How do I prevent the pattern validator from adding the $?
I suppose I could roll my own password validator, but surely there is a better solution...?

EDIT: Passwords that should succeed:

  • Test1234
  • tEst1234
  • tesT1234
  • 1234Test
  • 1234tesT
  • t#St1234

Passwords that should fail:

  • TEST1234
  • test1234
  • tEst123
  • Test123
  • testtest
  • 12345678

Validator declaration:

this.password = new FormControl('', [Validators.required, Validators.pattern('^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.{8,})')]);
this.userForm.addControl('Password', this.password);
1
  • Please give us one or two examples of what passwords you tried, and also how you declared your validator. Commented Aug 8, 2018 at 8:07

1 Answer 1

30

You may add a .* at the end, or even revamp the pattern a bit to convert one lookahead into a consuming pattern:

Validators.pattern('(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{8,}')

Or, better, when using a regex for password validation, follow the principle of contrast:

Validators.pattern('(?=[^A-Z]*[A-Z])(?=[^a-z]*[a-z])(?=[^0-9]*[0-9]).{8,}')

Angular will add ^ and $ on both ends of the regex pattern, so the pattern will look like

^(?=[^A-Z]*[A-Z])(?=[^a-z]*[a-z])(?=[^0-9]*[0-9]).{8,}$

Note it won't add the anchors automatically if you use a regex literal, add them manually:

Validators.pattern(/^(?=[^A-Z]*[A-Z])(?=[^a-z]*[a-z])(?=\D*\d).{8,}$/)

With a regex literal, you may use single backslashes in regex escapes (/\d/ to match a digit vs. "\\d" in a string literal).

See the regex demo

Details

  • ^ - start of string
  • (?=[^A-Z]*[A-Z]) - at least 1 uppercase ASCII letter
  • (?=[^a-z]*[a-z]) - at least 1 lowercase ASCII letter
  • (?=[^0-9]*[0-9]) - at least 1 ASCII digit
  • .{8,} - any 8 or more chars (other than line break chars)
  • $ - end of string.
Sign up to request clarification or add additional context in comments.

11 Comments

Changing the length lookahead to a consuming pattern solved it. Thanks.
Can i assign this dynamically i mean (?=[^A-Z]*[A-Z]) this code validates for 1 upper case letter what if i want 2 uppercase letters ?
@JigneshMistry Replace (?=[^A-Z]*[A-Z]) with (?=(?:[^A-Z]*[A-Z]){2})
Thanks buddy it worked :) Just one more trouble can u send the regex for 2 Numeric & 2 special characters ?
@JigneshMistry They are formed the same way as above.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.