[Solved] Angular 2+, why doesn’t material want to show error message?


*Update

To create a customFormControl over a control, we use parent, see an example

checkPasswords(): ValidatorFn {
    //see that the argument is a FormControl
    return (control: FormControl): ValidationErrors => {
      //the formGroup is control.parent
      const group = control.parent as FormGroup;
      //but we must sure that is defined
      if (!group) return null;
      console.log(group.get("password").value);
      let pass = group.get("password").value;
      let confirmPass = group.get("passwordConfirm").value;

      return confirmPass ? pass === confirmPass ? null : { mismatch: true } : null;
    };
  }

As we want to make check when password change too

ngOnInit() {
    this.form.get("password").valueChanges.subscribe(() => {
      this.form.get("passwordConfirm").updateValueAndValidity();
    });
  }

See that the form is like

form = new FormGroup({
    password: new FormControl("", Validators.required),
    passwordConfirm: new FormControl("", [
      Validators.required,
      this.checkPasswords()
    ])
  });

And the .html

<form [formGroup]="form" class="example-form">
  <mat-form-field class="example-full-width">
    <input matInput placeholder="password" formControlName="password">
        <mat-error >
      required
    </mat-error>

  </mat-form-field>
  <mat-form-field class="example-full-width">
    <input matInput placeholder="repeat password" formControlName="passwordConfirm"
           >
    <mat-error *ngIf="form.get('passwordConfirm').hasError('mismatch')">
      must matcher
    </mat-error>
    <mat-error *ngIf="form.get('passwordConfirm').hasError('required')">
      required
    </mat-error>
  </mat-form-field>
</form>

The stackblitz here

The other way is using a custom errorStateMatcher

Update 2 I said that other way is “use a errorStateMatcher.” A erroStateMatcher is a simple function that return true or false. If return true, our control will be marked as if he was invalid(*)

Imagine we has a form like

form = new FormGroup({
    password: new FormControl("", Validators.required),
    passwordConfirm: new FormControl("", [
      Validators.required,

    ])
  },this.checkPasswords());

See that error is belong to formGroup, we can create a customErrorMatcher that return true if control is invalid or if form.hasError(‘mismatch`)

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return !!((control && form.hasError('mismatch') || control.invalid) && control.touched );
  }
}

Well, the .html

<form [formGroup]="form" class="example-form">
  <mat-form-field class="example-full-width">
    <input matInput placeholder="password" formControlName="password">
        <mat-error >
      required
    </mat-error>

  </mat-form-field>
<!--see that the "errorStateMatcher" is applied to the input "passwordConfirm"-->
  <mat-form-field class="example-full-width">
    <input matInput placeholder="repeat password" formControlName="passwordConfirm"
    [errorStateMatcher]="matcher"
           >
      <!--here show the error is form.hasError('mismatch')-->
    <mat-error *ngIf="form.hasError('mismatch')">
      must matcher
    </mat-error>
       <!--here show the error is form.get('passwordConfirm').hasError-->
    <mat-error *ngIf="form.get('passwordConfirm').hasError('required')">
      required
    </mat-error>
  </mat-form-field>
</form>

As always I can, the stackblitz

(*) check in the stackblitz form.get(‘passwordConfirm’).invalid

5

solved Angular 2+, why doesn’t material want to show error message?