File

src/module/component/mat-password-strength/mat-password-strength.component.ts

Implements

OnInit OnChanges

Metadata

changeDetection ChangeDetectionStrategy.OnPush
exportAs matPasswordStrength
selector mat-password-strength
styleUrls ./mat-password-strength.component.scss
templateUrl ./mat-password-strength.component.html

Index

Properties
Methods
Inputs
Outputs
Accessors

Inputs

accentThreshold
Default value : 81
customValidator
Type : RegExp
enableDigitRule
Default value : true
enableLengthRule
Default value : true
enableLowerCaseLetterRule
Default value : true
enableSpecialCharRule
Default value : true
enableUpperCaseLetterRule
Default value : true
externalError
Type : boolean
max
Default value : 30
min
Default value : 8
password
Type : string
warnThreshold
Default value : 21

Outputs

onStrengthChanged
Type : EventEmitter<number>

Methods

Private _containAtLeastMinChars
_containAtLeastMinChars()
Returns : boolean
Private _containAtLeastOneDigit
_containAtLeastOneDigit()
Returns : boolean
Private _containAtLeastOneLowerCaseLetter
_containAtLeastOneLowerCaseLetter()
Returns : boolean
Private _containAtLeastOneSpecialChar
_containAtLeastOneSpecialChar()
Returns : boolean
Private _containAtLeastOneUpperCaseLetter
_containAtLeastOneUpperCaseLetter()
Returns : boolean
Private _containCustomChars
_containCustomChars()
Returns : boolean
calculatePasswordStrength
calculatePasswordStrength()
Returns : void
ngOnChanges
ngOnChanges(changes: SimpleChanges)
Parameters :
Name Type Optional
changes SimpleChanges No
Returns : void
ngOnInit
ngOnInit()
Returns : void
parseCustomValidatorsRegex
parseCustomValidatorsRegex(value: string | RegExp)
Parameters :
Name Type Optional Default value
value string | RegExp No this.customValidator
Returns : any
reset
reset()
Returns : void
setRulesAndValidators
setRulesAndValidators()
Returns : void

Properties

Private _color
Type : ThemePalette
Private _strength
Type : number
Default value : 0
containAtCustomChars
Type : boolean
containAtLeastMinChars
Type : boolean
containAtLeastOneDigit
Type : boolean
containAtLeastOneLowerCaseLetter
Type : boolean
containAtLeastOneSpecialChar
Type : boolean
containAtLeastOneUpperCaseLetter
Type : boolean
criteriaMap
Default value : new Map<Criteria, RegExp>()
matPasswordStrengthValidator
Default value : new MatPasswordStrengthValidator()
passwordConfirmationFormControl
Type : FormControl
Default value : new FormControl()
passwordFormControl
Type : FormControl
Default value : new FormControl()
Validators
Type : ValidatorFn
validatorsArray
Type : ValidatorFn[]
Default value : []

Accessors

strength
getstrength()
color
getcolor()
import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from '@angular/core';
import {FormControl, ValidatorFn, Validators} from '@angular/forms';
import {ThemePalette} from '@angular/material';
import {Criteria} from '../../enum/criteria.enum';
import {Colors} from '../../enum/colors.enum';
import {MatPasswordStrengthValidator} from '../../validator/mat-password-strength-validator';
import {RegExpValidator} from '../../validator/regexp.class';


@Component({
  selector: 'mat-password-strength',
  exportAs: 'matPasswordStrength',
  templateUrl: './mat-password-strength.component.html',
  styleUrls: ['./mat-password-strength.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MatPasswordStrengthComponent implements OnInit, OnChanges {

  @Input() password: string;
  @Input() externalError: boolean;

  @Input() enableLengthRule = true;
  @Input() enableLowerCaseLetterRule = true;
  @Input() enableUpperCaseLetterRule = true;
  @Input() enableDigitRule = true;
  @Input() enableSpecialCharRule = true;

  @Input() min = 8;
  @Input() max = 30;
  @Input() customValidator: RegExp;

  @Input() warnThreshold = 21;
  @Input() accentThreshold = 81;

  @Output()
  onStrengthChanged: EventEmitter<number> = new EventEmitter();

  criteriaMap = new Map<Criteria, RegExp>();

  containAtLeastMinChars: boolean;
  containAtLeastOneLowerCaseLetter: boolean;
  containAtLeastOneUpperCaseLetter: boolean;
  containAtLeastOneDigit: boolean;
  containAtLeastOneSpecialChar: boolean;
  containAtCustomChars: boolean;

  // TO ACCESS VIA CONTENT CHILD
  passwordFormControl: FormControl = new FormControl();
  passwordConfirmationFormControl: FormControl = new FormControl();

  validatorsArray: ValidatorFn[] = [];

  private _strength = 0;
  private _color: ThemePalette;

  Validators: ValidatorFn;
  matPasswordStrengthValidator = new MatPasswordStrengthValidator();

  ngOnInit(): void {
    this.setRulesAndValidators();

    if (this.password) {
      this.calculatePasswordStrength();
    }
  }

  ngOnChanges(changes: SimpleChanges): void {
    if ((changes.externalError && changes.externalError.firstChange) || changes.password.isFirstChange()) {
      return;
    } else if (changes.externalError && changes.externalError.currentValue) {
      this._color = Colors.warn;
      return;
    } else if (changes.password.previousValue === changes.password.currentValue && !changes.password.firstChange) {
      this.calculatePasswordStrength();
    } else {
      this.password && this.password.length > 0 ?
        this.calculatePasswordStrength() : this.reset();
    }
  }

  get strength(): number {
    return this._strength ? this._strength : 0;
  }

  get color(): ThemePalette {

    if (this._strength < this.warnThreshold) {
      return Colors.warn;
    } else if (this._strength < this.accentThreshold) {
      return Colors.accent;
    } else {
      return Colors.primary;
    }
  }

  private _containAtLeastMinChars(): boolean {
    this.containAtLeastMinChars = this.password.length >= this.min;
    return this.containAtLeastMinChars;
  }

  private _containAtLeastOneLowerCaseLetter(): boolean {
    this.containAtLeastOneLowerCaseLetter =
      this.criteriaMap
        .get(Criteria.at_least_one_lower_case_char)
        .test(this.password);
    return this.containAtLeastOneLowerCaseLetter;
  }

  private _containAtLeastOneUpperCaseLetter(): boolean {
    this.containAtLeastOneUpperCaseLetter =
      this.criteriaMap
        .get(Criteria.at_least_one_upper_case_char)
        .test(this.password);
    return this.containAtLeastOneUpperCaseLetter;
  }

  private _containAtLeastOneDigit(): boolean {
    this.containAtLeastOneDigit =
      this.criteriaMap
        .get(Criteria.at_least_one_digit_char)
        .test(this.password);
    return this.containAtLeastOneDigit;
  }

  private _containAtLeastOneSpecialChar(): boolean {
    this.containAtLeastOneSpecialChar =
      this.criteriaMap
        .get(Criteria.at_least_one_special_char)
        .test(this.password);
    return this.containAtLeastOneSpecialChar;
  }

  private _containCustomChars(): boolean {
    this.containAtCustomChars =
      this.criteriaMap
        .get(Criteria.at_custom_chars)
        .test(this.password);
    return this.containAtCustomChars;
  }

  parseCustomValidatorsRegex(value: string | RegExp = this.customValidator) {
    if (this.customValidator instanceof RegExp) {
      return this.customValidator;
    } else if (typeof this.customValidator === 'string') {
      return RegExp(this.customValidator);
    }
  }

  setRulesAndValidators(): void {
    this.validatorsArray = [];
    this.criteriaMap = new Map<Criteria, RegExp>();
    this.passwordConfirmationFormControl
      .setValidators(Validators.compose([
        Validators.required, this.matPasswordStrengthValidator.confirm(this.password)
      ]));
    this.validatorsArray.push(Validators.required);
    if (this.enableLengthRule) {
      this.criteriaMap.set(Criteria.at_least_eight_chars, RegExp(`^.{${this.min},${this.max}}$`));
      this.validatorsArray.push(Validators.minLength(this.min));
      this.validatorsArray.push(Validators.maxLength(this.max));
    }
    if (this.enableLowerCaseLetterRule) {
      this.criteriaMap.set(Criteria.at_least_one_lower_case_char, RegExpValidator.lowerCase);
      this.validatorsArray.push(Validators.pattern(RegExpValidator.lowerCase))
    }
    if (this.enableUpperCaseLetterRule) {
      this.criteriaMap.set(Criteria.at_least_one_upper_case_char, RegExpValidator.upperCase);
      this.validatorsArray.push(Validators.pattern(RegExpValidator.upperCase))
    }
    if (this.enableDigitRule) {
      this.criteriaMap.set(Criteria.at_least_one_digit_char, RegExpValidator.digit);
      this.validatorsArray.push(Validators.pattern(RegExpValidator.digit))
    }
    if (this.enableSpecialCharRule) {
      this.criteriaMap.set(Criteria.at_least_one_special_char, RegExpValidator.specialChar);
      this.validatorsArray.push(Validators.pattern(RegExpValidator.specialChar))
    }
    if (this.customValidator) {
      this.criteriaMap.set(Criteria.at_custom_chars, this.parseCustomValidatorsRegex());
      this.validatorsArray.push(Validators.pattern(this.parseCustomValidatorsRegex()))
    }

    this.criteriaMap.forEach((value: any, key: string) => {
      this.validatorsArray.push(this.matPasswordStrengthValidator.validate(key, value));
    });

    this.passwordFormControl.setValidators(Validators.compose([...this.validatorsArray]));
    this.Validators = Validators.compose([...this.validatorsArray]);

  }

  calculatePasswordStrength(): void {
    const requirements: Array<boolean> = [];
    const unit = 100 / this.criteriaMap.size;

    // console.log('this.criteriaMap.size = ', this.criteriaMap.size);
    // console.log('unit = ', unit);

    requirements.push(
      this.enableLengthRule ? this._containAtLeastMinChars() : false,
      this.enableLowerCaseLetterRule ? this._containAtLeastOneLowerCaseLetter() : false,
      this.enableUpperCaseLetterRule ? this._containAtLeastOneUpperCaseLetter() : false,
      this.enableDigitRule ? this._containAtLeastOneDigit() : false,
      this.enableSpecialCharRule ? this._containAtLeastOneSpecialChar() : false,
      this.customValidator ? this._containCustomChars() : false
    );

    this._strength = requirements.filter(v => v).length * unit;
    // console.log('length = ', this._strength / unit);
    this.onStrengthChanged.emit(this.strength);
    this.setRulesAndValidators();
  }

  reset() {
    this._strength = 0;
    this.containAtLeastMinChars =
      this.containAtLeastOneLowerCaseLetter =
        this.containAtLeastOneUpperCaseLetter =
          this.containAtLeastOneDigit =
            this.containAtCustomChars =
              this.containAtLeastOneSpecialChar = false;
  }
}
<mat-progress-bar mode="determinate"
                  [color]="color"
                  [value]="strength">
</mat-progress-bar>

./mat-password-strength.component.scss

.green :host::ng-deep .mat-progress-bar.mat-primary .mat-progress-bar-fill::after {
  background-color: #43A047;
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""