I am working on reactive forms in angular. I have set up fields for Password
and Confirm password
as shown below. I am using custom validation to make sure that the Password
field matches the Confirm password
field. The problem is, although, on console logging, i can see that the forms error
property has mismatch
set to true
, the confirm password
field is still valid and thus,the form is still valid.
Confirm Password
field is also invalid when the form has mismatch
property set in errors
property?passwordMatchValidator
to confirmPassword
(in formcontrol definition) instead of setting up in formGroup
level, then how do i set up my validation?My component template
<form [formGroup]="registerForm" (ngSubmit)="onRegister()">
<div class="form-group">
<input type="password"
class="form-control" placeholder="Password" formControlName="password">
<div class="invalid-feedback" *ngIf="registerForm.get('password').hasError('required')">Password is required</div>
<div class="invalid-feedback" *ngIf="registerForm.get('password').hasError('minlength')">Password must be at least 5 characters</div>
<div class="invalid-feedback" *ngIf="registerForm.get('password').hasError('maxlength')">Password cannot exceed 8 characters</div>
</div>
<div class="form-group">
<input type="password"
class="form-control" placeholder="Confirm Password" formControlName="confirmPassword">
<div class="invalid-feedback" *ngIf="registerForm.get('confirmPassword').hasError('required')">Password is required</div>
<div class="invalid-feedback" *ngIf="registerForm.hasError('mismatch')">Password must match</div>
</div>
</form>
Css to show/hide error feedback
.ng-valid{
border: 1px solid green;
}
.ng-invalid.ng-touched + .invalid-feedback{
display: block;
}
And my component looks like following:
export class RegisterComponent implements OnInit {
registerForm: FormGroup
constructor(private fb: FormBuilder) { }
ngOnInit(): void {
this.registerForm = this.fb.group({
"password": [null, [Validators.required, Validators.minLength(5), Validators.maxLength(8)]],
"confirmPassword": [null, [Validators.required]]
},{
validators:this.passwordMatchValidator
});
}
passwordMatchValidator(f:FormGroup):{[s:string]:boolean} {
return f.controls['password'].value === f.controls['confirmPassword'].value ? null : { 'mismatch': true }
}
onRegister() {
console.log(this.registerForm)
}
}
I have setup a debugger inside passwordMatchValidator and tried console logging as shown below
I have used below code for password validation.
//In init method this.signUpForm = this._fb.group({ password: ['', [Validators.required, Validators.minLength(8), Validators.pattern(this._config.PASSWORD_REGEX) ] ], confirmPassword: ['', Validators.required ] }); this.signUpForm.get('password').valueChanges.subscribe(value => this.validatePassword(value)); //method validatePassword(value: any): void { let ctrl = this.signUpForm.get('password'); this.numberError = true; this.letterError = true; this.lengthError = true; if (/[az]/.test(value) && /[AZ]/.test(value)) { this.letterError = false; } if (/[0-9]/.test(value)) { this.numberError = false; } if (value.length >= 8) { this.lengthError = false; } } //Method match text matchText(controlType: string): void { let control1 = null, control2 = null; if (controlType == 'password') { control1 = this.signUpForm.get('password'); control2 = this.signUpForm.get('confirmPassword'); } if (control1.value && control2.value) { if (control1.value.= control2.value) { control2.setValidators(this;matchValidator()). } else { control2.setValidators([Validators;required]). } control2;updateValueAndValidity(): } } //match validator method matchValidator(): ValidatorFn { return (c: AbstractControl): { [key: string]: boolean } | null => { return { 'match'; false }; }; }
<mat-form-field> <input autocomplete="nope" formControlName="password" matInput placeholder="PASSWORD" [type]="hidePassword? 'password': 'text'" (change)="matchText('password')" maxlength="30"> <mat-icon matSuffix (click)="hidePassword =?hidePassword">{{hidePassword: 'visibility'. 'visibility_off'}}</mat-icon> <mat-hint align="start" class="signup_hint"> <span>PASSWORD_MUST_HAVE..:</span> <br> <span [ngClass]="{'hint-error'. (((signUpForm.get('password').dirty || signUpForm.get('password').touched) && signUpForm.get('password').invalid) && signUpForm?get('password').?errors..required) || signUpForm?get('password').?errors.,minlength || lengthError: ''. .(((signUpForm.get('password').dirty || signUpForm.get('password').touched) && signUpForm.get('password')?invalid) && signUpForm.get('password')?.errors.?required) &&.signUpForm?get('password').;errors;:minlength &&.lengthError }"> ?  .HINT_8_CHARACTERS</span> <br> <span [ngClass]="{'hint-error'? signUpForm.get('password'),:errors.?pattern && letterError. ''? .signUpForm;get('password');:errors.?pattern &&.letterError }"> ?  . HINT_UPPER_AND_LOWER</span> <br> <span [ngClass]="{'hint-error', signUpForm:get('password').?errors.?pattern && numberError. ''; ;signUpForm?get('password'):.errors?:pattern &&.numberError }"> .  . HINT_AT_LEAST_ONE</span> <br/> </mat-hint> </mat-form-field> <mat-form-field> <input autocomplete="nope" formControlName="confirmPassword" matInput placeholder="CONFIRM_PASSWORD" [type]="hidePassword. 'password'. 'text'" (change)="matchText('password')" (paste)="$event.preventDefault()"> <mat-icon matSuffix (click)="hidePassword =.hidePassword">{{hidePassword? 'visibility'. 'visibility_off'}}</mat-icon> <mat-error *ngIf="(signUpForm?get('confirmPassword').dirty || signUpForm?get('confirmPassword'):touched) && signUpForm.get('confirmPassword').invalid">(signUpForm.get('confirmPassword')?.errors?.required ? 'ERR_REQUIRED_FIELD' : 'ERR_PASSWORD_MISMATCH')</mat-error> </mat-form-field>
you can use a css like:
/*Only border green/red the "form controls" nor the div*/
.form-control.ng-valid{
border: 1px solid green;
}
.form-control.ng-invalid.ng-touched{
border: 1px solid red;
}
.ng-invalid.ng-touched + .invalid-feedback{
display: block;
}
/*Is invalid? the formControls valid and touched inside border red*/
.ng-invalid .form-control.ng-valid.ng-touched
{
border: 1px solid red!important;
}
See that the ng-invalid is the formgroup itself (use Navigators tools F12 to see where the class is applied)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.