Cross Field Validation for password not invoked/working

42 views Asked by At

Clearly password and confirmPassword don,t match but still no error is being shownISSUE: creating a password validator to cross check with confirm password if it does not matches(as shown in passwordvalidator.ts) the input field would be red due to visual error in class is-invalid and aslo displays a small tag representing "password don't match "

HTML CODE:

<div class="container-fluid">
  <h2>Registration Form</h2>
  {{registrationForm.value | json}}
  <form [formGroup]="registrationForm">

    <div class="form-group"> 
      <label>Username</label>
      <input [class.is-invalid]="userName?.invalid && 
                               userName?.touched" formControlName="userName" type="text" class="form-control">
      
      <div *ngIf="userName?.invalid  && 
      userName?.touched">
     
       <small *ngIf="userName?.errors?.['required']" class="text-danger">Username is required</small>
        <small *ngIf="userName?.errors?.['minlength']" class="text-danger">Username must be of atleast 3
          characters</small>
        <small *ngIf="userName?.errors?.['forbiddenName']"
          class="text-danger">{{userName.errors?.['forbiddenName'].value}} Username not allowed</small>

      </div>
    </div>

    <div class="form-group">   
      <label>Email</label>
      <button type="button" class="btn btn-secondary btn-sm m-2"  (click)="addAlternateEmail()">Add e-mail</button>
      <input [class.is-invalid]="email.invalid && email.touched" type="email" class="form-control" formControlName="email">
      <small class="text-danger" [class.d-none]="email.valid || email.untouched">Email is required</small>
    <div formArrayName="alternateEmails" *ngFor = "let email of alternateEmails.controls; let i=index">
      <input type = "text" class ="form-control my-1" [formControlName]="i">

    </div>
    </div>

    <div class = "from-check mb-3">
      <input class="form-check-label" formControlName="subscribe" type="checkbox">
      <label class="form-check-label">
        Send me promotional offers
      </label>

    </div>

    <div class="form-group">
      <label>Password</label>
      <input formControlName="password" type="password" class="form-control">
    </div>

    <div class="form-group"> 
      <label>Confirm Password</label>
      <input [class.is-invalid]="registrationForm.errors?.['misMatch'] " formControlName="confirmPassword" type="password" class="form-control">
      <small class="text-danger" *ngIf="registrationForm.errors?.['misMatch']">Password do not match</small>

    </div>

    <div formGroupName="address">

      <div class="form-group">
        <label>City</label>
        <input formControlName="city" type="text" class="form-control">
      </div>

      <div class="form-group">
        <label>State</label>
        <input formControlName="state" type="text" class="form-control">
      </div>

      <div class="form-group">
        <label>Postal Code</label>
        <input formControlName="postalCode" type="text" class="form-control">
      </div>

    </div>

    <button class="btn btn-primary me-md-2" type="submit">Register</button>
    <button (click)="loadApiData()" class="btn btn-secondary" type="button">Load API Data</button>

  </form>

</div>

App.component.ts CODE

import { Component, OnInit } from '@angular/core';

import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms';
import { forbiddenNameValidator } from './shared/user-name.validator';
import { PasswordValidator } from './shared/password-validator';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  registrationForm!: FormGroup;

  get userName() {
    return this.registrationForm.get('userName');
  }

  get email() {
    return this.registrationForm.get('email');
  }
  get alternateEmails(){
    return this.registrationForm.get('alternateEmails') as FormArray;
  }

  addAlternateEmail(){
    this.alternateEmails.push(this.fb.control(''));
  }
  constructor(private fb: FormBuilder) { }

  ngOnInit(): void {

    this.registrationForm = this.fb.group({
      userName: ['', [Validators.required, Validators.minLength(3), forbiddenNameValidator(/admin/)]],
      email: [''],
      subscribe: [false],
      password: [''],
      confirmPassword: [''],
      address: this.fb.group({
        city: [''],
        state: [''],
        postalCode: ['']
      }),
      alternateEmails: this.fb.array([]),
    }, 
    { Validators: PasswordValidator });

    this.registrationForm.get('subscribe').valueChanges
      .subscribe(checkedValue => {  
        const email:any = this.registrationForm.get('email');
        if (checkedValue) {
          email.setValidators(Validators.required);
        }
        else {
          email.clearValidators();
        }
        email.updateValueAndValidity();

      })

  }  

  loadApiData() {

    this.registrationForm.patchValue({
      userName: 'Bruce',
      password: 'test',
      confirmPassword: 'test',

    });
  }

}

Module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Passwordvalidator.ts CODE

import { AbstractControl} from "@angular/forms";

 export function PasswordValidator(control: AbstractControl): {[key: string]: boolean} | null{
     const password = control.get('password');
     const confirmPassword = control.get('confirmPassword');
     if(password.pristine || confirmPassword.pristine){
      return null;
     }

     return password && confirmPassword && password.value !== confirmPassword.value ?
     {misMatch: true} : 
     null; 
    
 }
0

There are 0 answers