I want to add an error to my input ! The function will return true if the bith passwords are matching otherwise it will return false How can I call a boolean function in mat-error !
My Function:
checkPasswords(): Boolean { // here we have the 'passwords' group
this.test = false
let pass = this.changePassForm.value.motpasseconf;
let confirmPass = this.changePassForm.value.Nouveaumotpasse;
console.log(pass);
if (pass === confirmPass) {
return true;
}
}
The ERROR:
<mat-error *ngIf=" "> Not matching Password </mat-error>
The same function in the button works but annd in the error mat dosnt work
TS File:
ngOnInit(): void {
// initialisation du modifier password Form
this.changePassForm = this.formBuilder.group({
'userFullName': [this.user.firstName, [
]],
'Nouveaumotpasse': [this.user.motpasseconf, [
Validators.required,
Validators.minLength(6),
]],
'motpasseconf': [this.user.motpasseconf, [
Validators.required,
Validators.minLength(6),
]]
});
}
HTML Form:
<
div fxFlex="48" *ngIf="resultUserData != null || resultUserData != undefined">
<form [formGroup]="changePassForm" novalidate>
<mat-form-field >
<input id="userFullName" matInput formControlName="userFullName" placeholder="Nom et prénom de l'utilisateur concerné"
type="text" readonly/>
</mat-form-field>
<!-- Nouveau mot de passe -->
<mat-form-field >
<input id="Nouveaumotpasse" matInput #passwordWithValidation formControlName="Nouveaumotpasse"
placeholder="Nouveau mot de passe" [type]="hide ? 'password':'text'" required />
<mat-icon matSuffix (click)="hide= !hide" required color="primary">
{{ hide ? 'visibility' : 'visibility_off' }}
</mat-icon>
<mat-error *ngIf="changePassForm.controls['Nouveaumotpasse'].hasError('required')">Votre mot de passe est
<strong>obligatoire</strong>
</mat-error>
<mat-error
*ngIf="(changePassForm.controls['Nouveaumotpasse'].hasError('minlength')) && !changePassForm.controls['Nouveaumotpasse'].hasError('required') && changePassForm.controls['Nouveaumotpasse'].hasError('notEqual')">
Le Mot de passe doit comporter 6 caractères minimum
</mat-error>
<mat-error *ngIf="checkPasswords()">
Les mots de passe saisis ne sont pas identiques</mat-error>
</mat-form-field>
<!-- Confirmer nouveau mot de passe -->
<mat-form-field >
<input id="motpasseconf" matInput formControlName=motpasseconf placeholder="Confirmer nouveau mot de passe"
[type]="hide ? 'password':'text'" appConfirmEqualValidator="Nouveaumotpasse" required />
<mat-icon matSuffix (click)="hide= !hide" color="primary">
{{ hide ? 'visibility' : 'visibility_off' }}
</mat-icon>
<mat-error *ngIf="changePassForm.controls['motpasseconf'].hasError('required')">Retapez le mot de passe
pour confirmation </mat-error>
<mat-error
*ngIf="!changePassForm.controls['motpasseconf'].hasError('required') ">
Les mots de passe saisis ne sont pas identiques</mat-error>
</mat-form-field>
Please check edited post
Please check edited post
CodePudding user response:
Angular Material provides an elegant way to deal with errors where several fields are involved: the ErrorStateMatcher (https://material.angular.io/components/input/overview#changing-when-error-messages-are-shown)
Let's say you use reactive forms, you can use a custom validator match on the form group:
this.passwordForm = this.fb.group({
newPassword: ['', [Validators.required, password()]],
confirmPassword: ['', [Validators.required, password()]]
}, { validators: match('newPassword', 'confirmPassword') })
Here is the implementation of the match validator:
import { AbstractControl, ValidatorFn } from '@angular/forms'
import { error } from './error'
export function match(controlName: string, matchingControlName: string): ValidatorFn {
return (control: AbstractControl) => {
const value = control.get(controlName)?.value as string | null
const matchingValue = control.get(matchingControlName)?.value as string | null
return (value && matchingValue && value !== matchingValue) ? error('notMatching') : null
}
}
This validator will check that the two form control (they need to be in the form group on which the validator is applied) have the same value.
You will also need to implement an ErrorStateMatcher:
import { FormControl, FormGroupDirective, NgForm } from '@angular/forms'
import { ErrorStateMatcher } from '@angular/material/core'
export class CrossFieldErrorMatcher implements ErrorStateMatcher {
constructor(
private crossFieldError: string
) { }
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const isTouched = control?.touched ?? false
const isInvalid = control?.invalid ?? false
const hasCrossFieldError = form?.hasError(this.crossFieldError) ?? false
return isTouched && (isInvalid || hasCrossFieldError)
}
}
Don't forget to initialise it in your component's ts file:
crossFieldErrorMatcher = new CrossFieldErrorMatcher('notMatching')
The error state matcher will dictate when a field should be considered in error. The implementation here makes sure that the field it is applied to is considered in error if its parent has a certain error whose name is passed in the constructor. In our exemple, it will be 'notMatching'. If the error is detected on the form group then the confirm password field will be considered in error.
And then in your html:
<form (ngSubmit)="editPassword(f)" #f="ngForm" [formGroup]="passwordForm" autocomplete="off">
<mat-form-field>
<mat-label>New Password</mat-label>
<input matInput formControlName="newPassword" required autocomplete="new-password" id="new-password">
<mat-error ngs-error-message [formGroup]="passwordForm" propertyName="newPassword"></mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Confirm new password</mat-label>
<input matInput formControlName="confirmPassword" [errorStateMatcher]="crossFieldErrorMatcher" required autocomplete="new-password" id="new-password-confirmation">
<mat-error *ngIf="confirmPasswordControl.hasError('required')">
Confirm your password is required
</mat-error>
<mat-error *ngIf="passwordForm.hasError('notMatching')">
The two passwords don't match
</mat-error>
</mat-form-field>
<button mat-flat-button type="submit" color="accent"
[disabled]="passwordForm.invalid || !passwordForm.dirty || isLoading">
Submit
</button>
</form>