Search code examples
angularangular8angular-reactive-formsangular-validationangular-validator

Dynamic password validator in angular 8


Hi I have an api that returns an array object passwordPolicy that contains

PasswordMinLength: 6
passwordMinLowerCase: 1
passwordMinNumber: 1
passwordMinSymbol: 0
passwordMinUpperCase: 1

where the number can keep changing depending upon the role of a user example it can be

PasswordMinLength: Password min length.
PasswordMinLowerCase: This is currently either 0 or 1  So, if it's returning 1 for example it should have 1 minimum lower case. If it's returning 0 then the check should be ignored for lower case.
PasswordMinUpperCase: Same as above for upper case requirement.
PasswordMinSymbol: Same as above for symbol.
PasswordMinNumber: same as above to determine if a number is required in the password.

I know we can do validation using the regex pattern validation seeing the below How to validate password strength with Angular 5 Validator Pattern

but how to achieve validation DYNAMICALLY when the data keeps changing.

I need to validate the newpwdctrlname.

resetPwdForm: FormGroup = new FormGroup({
  newpwdctrlname: new FormControl('', [Validators.required, Validators.minLength(6)]),
  shownewpwdctrlname: new FormControl('', []),
  rptpwdctrlname: new FormControl('', [Validators.required])
});

Solution

  • You can generate the pattern dynamically using string interpolation

    Something like

      passRequirement = {
        passwordMinLowerCase: 1,
        passwordMinNumber: 1,
        passwordMinSymbol: 2,
        passwordMinUpperCase: 1,
        passwordMinCharacters: 8
      };
      pattern = [
        `(?=([^a-z]*[a-z])\{${this.passRequirement.passwordMinLowerCase},\})`,
        `(?=([^A-Z]*[A-Z])\{${this.passRequirement.passwordMinUpperCase},\})`,
        `(?=([^0-9]*[0-9])\{${this.passRequirement.passwordMinNumber},\})`,
        `(?=(\.\*[\$\@\$\!\%\*\?\&])\{${this.passRequirement.passwordMinSymbol},\})`,
        `[A-Za-z\\d\$\@\$\!\%\*\?\&\.]{${
          this.passRequirement.passwordMinCharacters
        },}`
      ]
        .map(item => item.toString())
        .join("");
      resetPwdForm = this.fb.group({
        newpwdctrlname: ['Passwod1@@5', [Validators.required, Validators.pattern(this.pattern)]],
        shownewpwdctrlname: ['', []],
        rptpwdctrlname: ['', [Validators.required]]
      });
      constructor (private fb: FormBuilder) {}
    

    You can then use this as

    Validators.pattern(this.pattern)
    

    See this demo on Stackblitz