Home > OS >  How can I call a function in mat-error element?
How can I call a function in mat-error element?

Time:03-22

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 enter image description here

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>
  • Related