LemmyLogic
LemmyLogic

Reputation: 1083

(Angular Material) mat-error message not showing inside mat-form-field

I'm doing some validation on mat-form-field inputs with Angular Material. The issue is that the mat-error message is not showing up, neither is the outline around the input field. I understand that there is a difference between using reactive forms and the template driven approach with ngModel. In my setup, I am using the latter. I've tried different things like using a template variable, using FormControl etc.

This happens when the mat-error element in inside the mat-form-field element, and when I Inspect the input field, I can see that the mat-error element is not being generated. If I move it outside the mat-form-field element, the error text is shown, but not the outline.

There is no form element around the mat-form-field elements that I can reference. The mat-form-field input fields are inside a mat-dialog.


<mat-dialog-content>
    <div class="select">
    <mat-form-field floatLabel="always">
          <input 
            type="text"
            (blur)="checkType()"
            [(ngModel)]="modelType"
            matInput
            placeholder="Enter type"
            [disabled]="false"
            required/>
          <mat-error *ngIf="typeExists">Type already exists!</mat-error>
        </mat-form-field>
    </div>
</mat-dialog-content>
    

component.ts

typeExists: boolean = false;
checkType()
  {
    //Code that looks in a list to see if the entered value exists in it.
    //It just sets a boolean value for typeExists, which is used to show the mat-error message

    this.typeExists = existsInList1;
  }

I have tried using a template variable like this with no luck:

<mat-dialog-content>
    <div class="select">
    <mat-form-field floatLabel="always">
          <input 
            type="text"
            (blur)="checkType()"
            [(ngModel)]="modelType"
            #typeInput="ngModel"
            matInput
            placeholder="Enter type"
            [disabled]="false"
            required/>
          <mat-error *ngIf="typeInput.dirty && typeExists">Type already exists!</mat-error>
        </mat-form-field>
    </div>
</mat-dialog-content>

Surely, I am not the only one who have had these issues, so I'm hoping someone can chip in.

Upvotes: 1

Views: 187

Answers (2)

Eliseo
Eliseo

Reputation: 57939

mat-error only is showed when the "input" is touched and "invalid". So, NOT can showed using a @if else validating the "formControl"

As you're using Template driven form you need use a directive. See the docs

@Directive({
  selector: '[checkIfExist]',
  providers: [
    { provide: NG_VALIDATORS, useExisting: CheckIfExistDirective, multi: true },
  ],
})
export class CheckIfExistDirective implements Validator {
  list = input<string[]>([], { alias: 'checkIfExist' });
  validate(control: AbstractControl): ValidationErrors | null {
    const typeExist = this.list().indexOf(control.value) >= 0;
    return typeExist ? { exist: true } : null;
  }
}

And use like

  <mat-form-field>
    <mat-label>Enter your email</mat-label>
    <input #emailID="ngModel" [checkIfExist]="your variable"
      matInput
      placeholder="[email protected]"
      [(ngModel)]="email"
      required
    />
    <mat-error>
      @if (emailID.errors?.exist) {
          yet in list
      } @else{
          required
      }
    </mat-error>
  </mat-form-field>

A stackblitz

Upvotes: 0

Naren Murali
Naren Murali

Reputation: 56828

Make sure you have added the below imports.

import {MatFormFieldModule} from '@angular/material/form-field';
import {MatInputModule} from '@angular/material/input';
...

...
@Component({
  selector: 'input-error-state-matcher-example',
  templateUrl: './input-error-state-matcher-example.html',
  styleUrl: './input-error-state-matcher-example.css',
  standalone: true,
  imports: [FormsModule, MatFormFieldModule, MatInputModule], // <- imports!
})
export class InputErrorStateMatcherExample {
  ...
}

Also ensure you have provideAnimations set in the bootstrapApplication level or in the app.module.ts level.

bootstrapApplication(InputErrorStateMatcherExample, {
  providers: [
    provideAnimations(),
    provideHttpClient(),
    importProvidersFrom(MatNativeDateModule)
  ]
}).catch(err => console.error(err));

Upvotes: 0

Related Questions