Стас Рябцев
Стас Рябцев

Reputation: 1398

Angular Material showing two error messages

I'm using angular material and reactive form. I want when errors messages are showing, only one message show and if I solve one error show another.

How it is now:

enter image description here

HTML:

<mat-form-field class="example-full-width">
  <input matInput
         placeholder="Username"
         name="username"
         [formControlName]="'username'">
  <mat-error *ngIf="form.controls['username'].errors && form.controls['username'].touched">
    <div *ngIf="form.controls['username'].errors.required">
      Username is <strong>required</strong>
    </div>
    <div *ngIf="form.controls['username'].errors.minlength">
      Required length: {{form.controls['username'].errors.minlength['requiredLength']}}
      Actual length:{{form.controls['username'].errors.minlength['actualLength']}}
    </div>
    <div *ngIf="form.controls['username'].errors.pattern">
      Only a-zA-Z0-9
    </div>

  </mat-error>

</mat-form-field>

Maybe I should use if else or something else? What do you think?

Upvotes: 8

Views: 13769

Answers (3)

Romko
Romko

Reputation: 1798

Was having the same problem. This is what I came up with, simple and elegant. No simultaneous mat-error's will be shown when there are two or more. Yet, the whole form will be invalid, disabling the submission.

mat-error + mat-error {
  display: none;
}

Upvotes: 7

brijmcq
brijmcq

Reputation: 3418

You are almost there. To display different error messages one at a time, just check the other errors if they exist.

<mat-error *ngIf="form.controls['username'].errors && form.controls['username'].touched">
  <div *ngIf="form.controls['username'].errors.required &&
    !form.controls['username'].errors.pattern 
    && form.controls['username'].errors.minlength">
    Username is <strong>required</strong> //this is the first message error
  </div>
  <div *ngIf="form.controls['username'].errors.minlength &&
        !form.controls['username'].errors.required &&
        !form.controls['username'].errors.pattern"> // display error if required and pattern errors don't exist Required length: {{form.controls['username'].errors.minlength['requiredLength']}}
    Actual length:{{form.controls['username'].errors.minlength['actualLength']}}
  </div>
  <div *ngIf="form.controls['username'].errors.pattern &&
                     !form.controls['username'].errors.required &&
                     !form.controls['username'].errors.minlength
                 ">
    Only a-zA-Z0-9
  </div>
</mat-error>

Basically just negate ! all the other error messages. This works for me.

Hope this helps.

Upvotes: -1

Milo
Milo

Reputation: 3443

You can have one <mat-error> check if the control is invalid and then get your appropriate error message i.e.:

<mat-error *ngIf="form.controls['username'].invalid">{{ getErrorMessage() }}</mat-error>

And then in your .ts you would have a function to retrieve the appropriate error message:

getErrorMessage() {
    return this.form.controls['username'].hasError('required') ? 'You must enter a value' :
        this.form.controls['username'].hasError('pattern') ? 'Not a valid username' :
        this.form.controls['username'].hasError('minlength') ? 'Required length is at least 3 characters' :
           '';
  }

You don't need those divs, the <mat-error> element should suffice if you have appropriate styles applied.

Here is a stackblitz example.

Upvotes: 17

Related Questions