• Skip to main content
  • Skip to primary sidebar

Web Development Archive

  • Archive
You are here: Home / Other / Password Validation

Password Validation

<form class="password-validator" [formGroup]="passwordForm">
<div class="password-validator-fields">
<app-field
class="mb-24"
[ngClass]="{ 'state-error': !isFormValid && passwordForm.get('password')?.touched }"
[fieldType]="FieldType.PASSWORD"
[label]="'SHARED.PASSWORD' | transloco"
[isIcon]="true"
[isIconRight]="true"
[fieldState]="passwordFieldState"
formControlName="password"
></app-field>
<app-field
class="mb-24"
[ngClass]="{ 'state-error': !isFormValid && passwordAgainTouched }"
[fieldType]="FieldType.PASSWORD"
[label]="'SHARED.PASSWORD_AGAIN' | transloco"
[isIcon]="true"
[isIconRight]="true"
[fieldState]="passwordAgainFieldState"
formControlName="passwordAgain"
></app-field>
</div>
<div class="password-validator-message">
<app-password-check
[validationText]="'AUTH.MIN_CHARACTER' | transloco"
[isValid]="isMinCharacter"
></app-password-check>
<app-password-check
[validationText]="'AUTH.MIN_LOWERCASE' | transloco"
[isValid]="hasMinLowercase"
></app-password-check>
<app-password-check
[validationText]="'AUTH.MIN_UPPERCASE' | transloco"
[isValid]="hasMinUppercase"
></app-password-check>
<app-password-check
[validationText]="'AUTH.MIN_NUMBER' | transloco"
[isValid]="hasMinNumber"
></app-password-check>
<app-password-check
*ngIf="passwordsMismatch && passwordAgainTouched"
[validationText]="'AUTH.PASSWORD_MISMATCH' | transloco"
[isValid]="!passwordsMismatch"
></app-password-check>
</div>
</form>
import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import {
AbstractControl,
FormBuilder,
FormGroup,
ReactiveFormsModule,
ValidationErrors,
ValidatorFn,
Validators,
} from '@angular/forms';
import { FieldComponent } from '@app/lib/components/field/field.component';
import { FieldState, FieldType } from '@app/lib/components/field/field.enum';
import { PasswordCheckComponent } from '@app/lib/components/password-check/password-check.component';
import { TranslocoPipe } from '@jsverse/transloco';

@Component({
selector: 'app-password-validator',
standalone: true,
imports: [CommonModule, FieldComponent, TranslocoPipe, PasswordCheckComponent, ReactiveFormsModule],
templateUrl: './password-validator.component.html',
styleUrls: ['./password-validator.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PasswordValidatorComponent implements OnInit {
passwordForm: FormGroup;

@Input() validationText: string;

isFormValid: boolean = false;

FieldType = FieldType;
FieldState = FieldState;

constructor(private readonly fb: FormBuilder) {
this.passwordForm = this.fb.group(
{
password: ['', [Validators.required, Validators.minLength(8)]],
passwordAgain: ['', Validators.required],
},
{ validators: this.passwordsMatch() },
);
}

ngOnInit(): void {
this.passwordForm.valueChanges.subscribe(() => {
this.checkFormValidity();
});
}

private passwordsMatch(): ValidatorFn {
return (formGroup: AbstractControl): ValidationErrors | null => {
const passwordControl = formGroup.get('password');
const passwordAgainControl = formGroup.get('passwordAgain');

if (!passwordControl || !passwordAgainControl) {
return null;
}

const password = passwordControl.value;
const passwordAgain = passwordAgainControl.value;

return password === passwordAgain ? null : { passwordsMismatch: true };
};
}

get isMinCharacter(): boolean {
return (this.passwordForm.get('password')?.valid && this.passwordForm.get('password')?.value?.length >= 8) || false;
}

get hasMinLowercase(): boolean {
return /[a-z]/.test(this.passwordForm.get('password')?.value || '');
}

get hasMinUppercase(): boolean {
return /[A-Z]/.test(this.passwordForm.get('password')?.value || '');
}

get hasMinNumber(): boolean {
return /[0-9]/.test(this.passwordForm.get('password')?.value || '');
}

get passwordsMismatch(): boolean {
return this.passwordForm.hasError('passwordsMismatch');
}

get passwordAgainTouched(): boolean {
return this.passwordForm.get('passwordAgain')?.touched || false;
}

get passwordFieldState(): FieldState {
return !this.isFormValid && this.passwordForm.get('password')?.touched
? this.FieldState.ERROR
: this.FieldState.DEFAULT;
}

get passwordAgainFieldState(): FieldState {
return !this.isFormValid && this.passwordAgainTouched ? this.FieldState.ERROR : this.FieldState.DEFAULT;
}

private checkFormValidity(): void {
this.isFormValid =
this.isMinCharacter &&
this.hasMinLowercase &&
this.hasMinUppercase &&
this.hasMinNumber &&
!this.passwordsMismatch &&
this.passwordForm.valid;
console.log(this.isFormValid ? 'Valid' : 'Not valid');
}
}

Filed Under: Other

About Gabor Flamich

I'm a web developer and designer based in Budapest, Hungary. In recent years, I've documented hundreds of solutions I came across during development. This site is an archive for useful code snippets on WordPress, Genesis Framework and WooCommerce. If You have any questions related to WordPress development, get in touch!

Primary Sidebar

  • angular.io
© 2026 WP Flames - All Right Reserved