Tirth shah
Tirth shah

Reputation: 13

Can we use <mat-error></mat-error> inside a *For* loop in Angular

I have created a common component. I am stuck in a problem where I am using angular material and using mat-form-field. I am using @if in angular 18 to check for a condition then mat-error is working fine. But when I am using @for it is not working and mat-error is showing inside input field not in mat-error. Also I need put my condition like this:

Above is the required format I am looking for. But I tried using single @if and @for as well. But @for is not working. Here is the output when I am using @for:

  1. First Image shows that error is coming inside a inputFor loop output when using with mat-error
@if(condition){
    @for(condition){
        <mat-error>{{error}}</mat-error>
    }
}

    <mat-form-field>
        <mat-label >{{label}}</mat-label>
            <input matInput [ngClass]="{'is-invalid': this.formGroup.get(controlName)?.invalid && this.formGroup.get(controlName)?.touched}" [formControlName]="controlName" (focus)="triggerValidation(controlName)" [required]="required" [type]="type" [placeholder]="placeholder">
                 @if(formGroup.get(controlName)?.invalid && formGroup.get(controlName)?.touched){
                     @for(error of getErrorMessages(controlName); track i; let i = $index){
                         <mat-error> {{ error }} </mat-error >
                      }
    }
    </mat-form-field>

I tried using ng-container. But for now ng-container is of no use as we have @if and @for block. I am looking for below output using @if and @else:

  1. Here is the output of my image:

Expected Output, currently I have used only @if so I am getting this output

Output which I am expecting

Upvotes: 1

Views: 75

Answers (2)

Naren Murali
Naren Murali

Reputation: 57696

I think this is a bug, so I raised the same on github:

MAT INPUT: The error messages show inside the form field, when a @if and @for are used to show the error messages. #30151

You can follow this bug to know more about this issue.


As a temporary workaround, you can simply use [hidden] to hide the errors and emulate the same behavior as the if condition.

<form class="example-form">
  <mat-form-field>
    <mat-label>Email</mat-label>
    <input
      type="email"
      matInput
      [formControl]="emailFormControl"
      [errorStateMatcher]="matcher"
      placeholder="Ex. pat@example.com"
    />
    @for(error of getErrorMessages(''); track i; let i = $index){
    <mat-error
      [hidden]="!(emailFormControl?.invalid && emailFormControl?.touched)"
    >
      {{ error }}
    </mat-error>
    }
  </mat-form-field>
</form>

Stackblitz Demo

Upvotes: 0

Lost Astrophile
Lost Astrophile

Reputation: 16

I don't know why you are doing @for for <mat-error>. You can just call getErrorMessages(controlName) within <mat-error>.

<mat-form-field>
  <mat-label>{{label}}</mat-label>
  <input matInput [ngClass]="{'is-invalid': this.formGroup.get(controlName)?.invalid && this.formGroup.get(controlName)?.touched}"
    [formControlName]="controlName" (focus)="triggerValidation(controlName)" [required]="required" 
    [type]="type" [placeholder]="placeholder">
  @if(formGroup.get(controlName)?.invalid && formGroup.get(controlName)?.touched){
    <mat-error> {{ getErrorMessages(controlName) }} </mat-error>
  }
</mat-form-field>

In your getErrorMessages() function make sure you are returning error messages if a control has an error or return '' if there is no error.

Upvotes: 0

Related Questions