How to validate password strength with Angular 5 Validator Pattern How to validate password strength with Angular 5 Validator Pattern angular angular

How to validate password strength with Angular 5 Validator Pattern


I took a stab at this with Angular's built-in pattern validator and was able to come up with the following that checks for:

  • At least 8 characters in length
  • Lowercase letters
  • Uppercase letters
  • Numbers
  • Special characters

    password: [  '',  [    Validators.required,    Validators.pattern('(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&].{8,}')   ]]

I'll add that I'm by no means a regex expert. This is simply what worked for me for a closely related case to the OP. Maybe it will help someone else. Mozilla's documentation helped a lot in figuring this out, specifically the Writing a regular expression pattern section.


I´ve not been able to use correctly the Validator Pattern, so I made a Custom Validator, and validate the password field string with three simple regex.
Anyway, I look forward to use correctly the Angular Validator Pattern.

Custom Validator

// password.validator.tsimport { FormControl } from '@angular/forms';export interface ValidationResult {    [key: string]: boolean;}export class PasswordValidator {    public static strong(control: FormControl): ValidationResult {        let hasNumber = /\d/.test(control.value);        let hasUpper = /[A-Z]/.test(control.value);        let hasLower = /[a-z]/.test(control.value);        // console.log('Num, Upp, Low', hasNumber, hasUpper, hasLower);        const valid = hasNumber && hasUpper && hasLower;        if (!valid) {            // return what´s not valid            return { strong: true };        }        return null;    }}

Replaced the Validator Pattern with my Custom Validator

// signup.component.tsimport { Component } from '@angular/core';import { FormBuilder, FormGroup, Validators } from '@angular/forms';import { PasswordValidator } from 'validators/password.validator';@Component({    selector: 'signup',    templateUrl: './signup.component.html',    styleUrls: ['./signup.component.scss']})export class SignupComponent {    form: FormGroup;    constructor() {        this.init();    }    init() {        this.form = this.fb.group({            name: ['', [Validators.required]],            email: ['', [Validators.required, Validators.email],            password: ['', [                Validators.required,                 PasswordValidator.strong            ]]        });     }}


If you have a look at Validator.js, you will notice that you may pass both a string or a regex literal to the Validators.pattern.

Regex passed as a string literal

  • The whole string must match the pattern (i.e. the pattern is anchored on both sides)
  • Backslashes can form string escape sequences and you must use double backslashes to define a literal backslash that is used to define a regex escape. So, to define a digit matching pattern, use '\\d', to define a whitespace pattern use '\\s', to define a backslash, use '\\\\'.

Regex passed as a regex literal

  • The regex does not automatically require a full string match.
  • Use single backslashes to define regex escapes (e.g. /\s+/)

So, what you may use is either of the two:

this.form = this.fb.group({    name: ['', [Validators.required]],    email: ['', [Validators.required, Validators.email],    password: ['', [        Validators.required,         Validators.pattern('(?=\\D*\\d)(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z]).{8,30}') ]]});

Or

this.form = this.fb.group({    name: ['', [Validators.required]],    email: ['', [Validators.required, Validators.email],    password: ['', [        Validators.required,         Validators.pattern(/^(?=\D*\d)(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z]).{8,30}$/) ]]});

Regex details

Note that the pattern changes I suggest are merely those related to the principle of contrast:

  • ^ - start of string (implicit in string regex pattern)
  • (?=\D*\d) - there must be 1 digit
  • (?=[^a-z]*[a-z]) - there must be 1 lowercase ASCII letter
  • (?=[^A-Z]*[A-Z]) - there must be 1 uppercase ASCII letter
  • .{8,30} - any 8 to 30 chars other than line break chars
  • $ - end of string (implicit in string regex pattern).