Website-Suche

angular - Beide mat-error werden angezeigt, wenn nur eine Bedingung wahr ist


Beide Mat-Fehler werden angezeigt, wenn nur ein Fehler aufgetreten ist.

Ich versuche, benutzerdefinierte Validatoren mit mat-error zu erstellen. Sowohl das Eingabefeld für E-Mail als auch das für die Bestätigung des Passworts sind rot, wenn jeder von ihnen einen wahren Wert für hasError('') hat.

Ich glaube, die Logik meiner MyErrorStateMatcher-Klasse ist irgendwie falsch. Bitte helfen Sie mir! Ich habe alles versucht, was ich konnte. Vielen Dank im Voraus!

Bild

Wie Sie im Bild sehen können. Wenn confirmPassword einen Fehler auslöst, ist auch das E-Mail-Feld rot.

Mein ErrorStateMatcher:

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const invalidCtrl = !!(control && control.invalid && (control.dirty || control.touched));
    const invalidParent = !!(control && (control.parent.hasError('notTheSame') || control.parent.hasError('emailUsed')));

    return ((invalidCtrl || invalidParent));
  }
}

HTML: (fokussieren Sie sich auf E-Mail und confimPassword)

<form [formGroup]="signupForm" (ngSubmit)="signup(signupForm)">
        <mat-form-field style="width: 100%;">
          <input matInput formControlName="email" placeholder="Email address" type="email" [errorStateMatcher]="matcher" required>
          <mat-error *ngIf="signupForm.controls.email.hasError('required')">Email required!</mat-error>
          <mat-error *ngIf="signupForm.controls.email.hasError('email')">Email invalid!</mat-error>
          <mat-error *ngIf="signupForm.hasError('emailUsed')">This email already exists!</mat-error>
        </mat-form-field>
        <mat-form-field style="width: 100%;">
          <input matInput formControlName="username" placeholder="User name" (blur)="signupForm.value.username != null ? isValidUsername(signupForm.value.username) : ''" required />
          <mat-error>Please enter your new username!</mat-error>
          <mat-error *ngIf="usernameInvalid">Username already exists!</mat-error>
        </mat-form-field>
        <mat-form-field style="width: 100%;">
          <input matInput formControlName="password" placeholder="New password" [type]="show ? 'text' : 'password'" required />
          <mat-icon matSuffix (click)="show = !show" style="cursor: pointer;">{{show ? 'visibility' : 'visibility_off'}}</mat-icon>
          <mat-error>Please enter your password!</mat-error>
        </mat-form-field>
        <mat-form-field style="width: 100%;">
          <input matInput formControlName="confirmPassword" placeholder="Confirm password" type="password" [errorStateMatcher]="matcher" required>
          <mat-error *ngIf="signupForm.controls.confirmPassword.hasError('required')">Please confirm your password!</mat-error>
          <mat-error *ngIf="signupForm.hasError('notTheSame') && signupForm.value.confirmPassword != ''">Password is not the same!</mat-error>
        </mat-form-field>
        <br>
      <button mat-raised-button class="sessionBtn" color="primary" [disabled]="signupForm.invalid">Submit!</button>
</form>

TS :

signupForm = new FormGroup({
    firstName: new FormControl(),
    lastName: new FormControl(),
    email: new FormControl('', [
      Validators.required,
      Validators.email
    ]),
    username: new FormControl(),
    password: new FormControl('', [
      Validators.required
    ]),
    confirmPassword: new FormControl('', [
      Validators.required
    ])
  }, { validators: [this.checkPassword, this.checkExistingEmail] });
  matcher = new MyErrorStateMatcher();

/////////Custom validator////////

  checkPassword(signupForm: FormGroup) {
    let password = signupForm.value.password;
    let confirmPassword = signupForm.value.confirmPassword;

    return password === confirmPassword ? null : { notTheSame: true };
  }

  checkExistingEmail(signupForm: FormGroup) {
    let inputEmail = signupForm.value.email;
    let dbEmail = "[email ";

    return inputEmail !== dbEmail ? null: { emailUsed: true };
  }

Fehler ist mit der Eingabe-E-Mail und der Eingabe-BestätigungPasswort aufgetreten, beide haben [errorStateMatcher]="matcher"

Antwort #1

Erstellen eines benutzerdefinierten Fehlervergleichers

Nun, wenn wir einen Fehler in einem <mat-form-field> anzeigen möchten, wenn das input gültig ist, verwenden wir einen customErrorMatcher.

Das ist eine Klasse wie

class CrossFieldErrorMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    //when we want to show the error
    return true 
    //when we want not show the error
    return false
  }
}

Normalerweise hatten wir in unserer Komponente

  errorMatcher=new CrossFieldErrorMatcher()
  //and the .html
  <mat-form-field>
    <input matInput formControlName='verifyPassword' 
        [errorStateMatcher]="errorMatcher">
    <mat-error *ngIf="....">
      Passwords do not match!
    </mat-error>
  </mat-form-field>

Nun, wir ändern die Dinge ein wenig, indem wir einen Konstruktor in unserem CustomErrorMatcher hinzufügen

class CrossFieldErrorMatcher implements ErrorStateMatcher {
  constructor(private name:string){}  //<--add a constructor
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    //when we want to show the error, but we can use "name"
    return true 
    //when we want not show the error
    return false
  }
}

Dann wird unsere Komponente

  errorMatcher(name:string)
  {
    return new CrossFieldErrorMatcher(name);
  }

  //and the .html
  <mat-form-field>
    <input matInput formControlName='verifyPassword' 
        [errorStateMatcher]="errorMatcher('password')">
    <mat-error *ngIf="....">
      Passwords do not match!
    </mat-error>
  </mat-form-field>

Antwort #2

Das E-Mail-Adressfeld zeigt einen Fehler an, weil der Fehlerzustandsabgleich das übergeordnete Element prüft - also das Formular - das einen Fehler aufweist, weil die Passwortfelder nicht übereinstimmen. Sie müssen verschiedene Fehlerzustandsabgleicher für das E-Mail-Feld und die Passwortfelder verwenden, da die Bedingungen unterschiedlich sind - die E-Mail muss keinen Fehler anzeigen, wenn die Passwortfelder nicht übereinstimmen.