Your answer came close. But according to the documentation, the regular expression used in the attribute pattern
must be a valid regex in Javascript. So I ran a test with your regex:
let r = /(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[@-#-$])(?=^.{8,50}$).*$/;
I tested the above code in Chrome, and gave this error:
Uncaught SyntaxError: Invalid regular expression: /(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[@-#-$])(?=^.{8,50}$).*$/:
Range out of order in character class
That is, the regex is invalid. The problem is that the documentation says that if regex is invalid, the attribute pattern
is ignored. Therefore, when using it in HTML, the error goes unnoticed.
The problem is in the section that checks the special characters: the hyphens in [@-#-$]
cause the error. Within brackets, hyphens have special meaning, as they serve to define a range (such as [a-z]
, defining an interval of a
to z
).
Only that the breaks accept any characters, then the regex interprets the passage @-#
as the interval between characters @
and #
. And if you look at ascii table, will see that the #
comes before the @
, then the range is invalid (this is what the error message says: "Range out of order"). It’s like I tried to use [z-a]
, which is invalid because the a
comes before the z
in the ASCII table (see).
So the first thing to do is to remove these hyphens and leave only the characters you want to check.
Then I also recommend putting the bookmark ^
at the beginning of the expression. This is better because of the lookaheads (the passages that begin with (?=
), since they check if something exists and then return to where it was. Using ^
before them, I guarantee that the search for characters always occurs at the beginning of the string.
Without the ^
, regex can repeat searches several times (first starting at the beginning of the string, then starting from the second character, and so on). This is a problem for invalid strings, because regex takes longer to realize that it is invalid: see here that without the ^
it takes more than 160 steps to realize that the string is invalid. Already using ^
she takes only 34 steps - The exact amount of steps can vary according to the size of the string, and of course for small strings it won’t have as much difference in performance, but anyway it’s a simple optimization and I prefer to do it. In addition, the use of ^
, together with the $
(meaning the end of the string), also ensures that the string will only have what is in regex.
Another detail is the .{8,50}
(between 8 and 50 characters). The dot corresponds to any character, so your password may be, for example, Abc123@!
(see). Notice that it has the character !
, and this is perfectly valid, since the Lookahead (?=.*[@#$])
only requires that there be at least one of @#$
, but the dot accepts any other characters (so .{8,50}
also accepts the !
).
If you want the password to have only letters, numbers and @#$
, simply change the regex to:
/* deixa uma borda vermelha enquanto o campo estiver inválido */
input:invalid {
border: 1px solid red;
}
<form>
<label for="senha">Senha:</label>
<input type="password" id="senha" name="senha" placeholder="Senha"
pattern="^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[@#$])[a-zA-Z0-9@#$]{8,50}$" required />
</form>
At the beginning we have ^
(string start), and then we have the lookaheads, each checking whether there is a certain character type (uppercase, lowercase, digit or one of the characters @#$
). Each Lookahead checks if a character type exists and returns to where it was (in this case, the beginning of the string), and then continues to evaluate the rest of the expression.
Instead of the point, I use [a-zA-Z0-9@#$]
, which makes regex no longer accept !
(or any other character that is not between the brackets). Now she only accepts what is in this list: letters, numbers or @#$
. And the quantifier {8,50}
indicates the minimum (8) and maximum (50) of these characters.
Recalling that the [a-zA-Z0-9@#$]
alone does not require it to have at least an uppercase letter, a lowercase letter, a number and a special character. It only requires the characters to be any of the characters in this list, so if I used only that and the password only had several letters A
, it would be valid (see). To force each character type to exist (letters, numbers, etc), the lookaheads.
I almost managed using this: <input class="form-control" type="password" id="password" name="password" placeholder="Password" Pattern="(?=.[A-Z])(?=.[a-z])(?=.[0-9])(?=.\W+)(?= . {8,50}$). *$" required />. But this way it allows the entry of any special character. And I’d just like to allow the special characters (@#$).
– Gato de Schrödinger