NgxMatErrors provides an easy yet flexible solution for displaying error messages in a MatFormField.
See it in action on StackBlitz.
Install ngx-mat-errors in your project:
npm install ngx-mat-errorsImport NgxMatErrorsModule and provide NGX_MAT_ERROR_CONFIG_EN (or your custom error messages) in your app.module.ts.
import { NgxMatErrorsModule, NGX_MAT_ERROR_CONFIG_EN } from "ngx-mat-errors"; @NgModule({ imports: [ ..., NgxMatErrorsModule ], providers: [NGX_MAT_ERROR_CONFIG_EN], }) export class AppModule {}Or you can import only NgxMatErrors and NgxMatErrorDef as they are marked standalone.
import { NgxMatErrors, NgxMatErrorDef, NGX_MAT_ERROR_CONFIG_EN } from "ngx-mat-errors"; @NgModule({ imports: [ ..., NgxMatErrors, NgxMatErrorDef ], providers: [NGX_MAT_ERROR_CONFIG_EN], }) export class AppModule {}Add [ngx-mat-errors] to your mat-error in your mat-form-field.
<mat-form-field> <mat-label>Label</mat-label> <input type="text" matInput [formControl]="control" /> <mat-error ngx-mat-errors></mat-error> </mat-form-field>ngx-mat-errors can be used as an @Input() to assign a control manually.
<mat-form-field> <mat-label>Label</mat-label> <input type="text" matInput [formControl]="control" autocomplete="off" /> </mat-form-field> <mat-error [ngx-mat-errors]="control"></mat-error><mat-form-field> <mat-label>Label</mat-label> <input type="text" matInput #control="ngModel" [(ngModel)]="input" autocomplete="off" /> </mat-form-field> <mat-error [ngx-mat-errors]="control"></mat-error>It can display errors for multiple controls, one at a time. The order of the controls is important; the first control with an error will be displayed.
<mat-form-field> <mat-label>Label</mat-label> <mat-date-range-input [rangePicker]="dateRangePicker"> <input matStartDate [formControl]="startControl" /> <input matEndDate [formControl]="endControl" /> </mat-date-range-input> <mat-date-range-picker #dateRangePicker></mat-date-range-picker> <mat-error [ngx-mat-errors]="[startControl, endControl]"></mat-error> </mat-form-field>import { NgxMatErrorsForDateRangePicker } from "ngx-mat-errors";You can use the [forDateRangePicker] standalone directive to display errors for the MatDateRangePicker component. The directive assigns the controls used in the MatDateRangeInput to the NgxMatErrors component.
<mat-form-field> <mat-label>Label</mat-label> <mat-date-range-input [rangePicker]="dateRangePicker"> <input matStartDate formControlName="start" /> <input matEndDate formControlName="end" /> </mat-date-range-input> <mat-date-range-picker #dateRangePicker></mat-date-range-picker> <mat-error ngx-mat-errors forDateRangePicker></mat-error> </mat-form-field>You can easily create directives like this to display errors in a MatFormField with multiple controls, look fot the implementation of NgxMatErrorsForDateRangePicker.
There are two ways to customize your error messages.
There is the NGX_MAT_ERROR_DEFAULT_OPTIONS injection token. You can provide it in your app.module.ts with useClass or useFactory and customize your error messages globally.
This example changes only the min error message.
import { errorMessagesEnFactory, NGX_MAT_ERROR_DEFAULT_OPTIONS } from 'ngx-mat-errors'; import { FactoryProvider, LOCALE_ID } from '@angular/core'; export const NGX_MAT_ERROR_DEFAULT_CONFIG: FactoryProvider = { useFactory: (locale: string) => ({ ...errorMessagesEnFactory(locale), min: (error: MinError) => `Min value is ${error.min}, actual is ${error.actual}`, }), provide: NGX_MAT_ERROR_DEFAULT_OPTIONS, deps: [LOCALE_ID], }; @NgModule({ ... providers: [NGX_MAT_ERROR_DEFAULT_CONFIG], }) export class AppModule {}You can provide an Observable<ErrorMessages> too, which allows changes of error messages. This comes in handy when your app supports JIT localization with libraries like @ngx-translate.
import { NGX_MAT_ERROR_DEFAULT_OPTIONS } from 'ngx-mat-errors'; import { FactoryProvider, LOCALE_ID } from '@angular/core'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { Observable, startWith, map } from 'rxjs'; export const NGX_MAT_ERROR_DEFAULT_CONFIG: FactoryProvider = { useFactory: ( locale: string, translateService: TranslateService ): Observable<ErrorMessages> => translateService.onLangChange.pipe( startWith(null), map(() => ({ required: translateService.instant('core.validations.required'), minlength: (error: MinError) => translateService.instant('core.validations.minlength', error), ... })) ), provide: NGX_MAT_ERROR_DEFAULT_OPTIONS, deps: [LOCALE_ID, TranslateService], }; @NgModule({ ... providers: [NGX_MAT_ERROR_DEFAULT_CONFIG], }) export class AppModule {}You can customize your error messages even more with the *ngxMatErrorDef directive.
<mat-form-field> <mat-label>Label</mat-label> <input type="text" matInput [formControl]="control1" /> <mat-error ngx-mat-errors> <span *ngxMatErrorDef="let error; for: 'pattern'"> Only digits are allowed, up to 12 digits. </span> <ng-container *ngxMatErrorDef="let error; for: 'min'"> The minimum value is {{ error.min }}. </ng-container> </mat-error> </mat-form-field>When used with multiple controls, you can specify the control for which the error message is intended.
<mat-form-field> <mat-label>Label</mat-label> <mat-date-range-input [rangePicker]="dateRangePicker"> <input matStartDate formControlName="start" /> <input matEndDate [formControl]="endControl" /> </mat-date-range-input> <mat-date-range-picker #dateRangePicker></mat-date-range-picker> <mat-error ngx-mat-errors forDateRangePicker> <span *ngxMatErrorDef="let error; for: 'required', withControl: 'start'">Start date is required.</span> <span *ngxMatErrorDef="let error; for: 'required', withControl: endControl">End date is required.</span> </mat-error> </mat-form-field>@angular/core: ^19.0.0 || ^20.0.0@angular/material: ^19.0.0 || ^20.0.0
<mat-form-field> <mat-label>Label</mat-label> <input type="text" matInput [formControl]="control" /> <mat-error ngx-mat-errors></mat-error> </mat-form-field><mat-error [ngx-mat-errors]="control"></mat-error> <mat-form-field> <mat-label>Label</mat-label> <input type="text" matInput [formControl]="control" /> </mat-form-field><mat-form-field> <mat-label>Label</mat-label> <mat-date-range-input [rangePicker]="dateRangePicker"> <input matStartDate [formControl]="startControl" /> <input matEndDate [formControl]="endControl" /> </mat-date-range-input> <mat-date-range-picker #dateRangePicker></mat-date-range-picker> <mat-error [ngx-mat-errors]="[startControl, endControl]"></mat-error> </mat-form-field><mat-form-field> <mat-label>Label</mat-label> <input type="text" matInput [(ngModel)]="value" /> <mat-error ngx-mat-errors></mat-error> </mat-form-field><mat-error [ngx-mat-errors]="control"></mat-error> <mat-form-field> <mat-label>Label</mat-label> <input type="text" matInput #control="ngModel" [(ngModel)]="value" /> </mat-form-field><mat-form-field> <mat-label>Label</mat-label> <mat-date-range-input [rangePicker]="dateRangePicker"> <input matStartDate #startControl="ngModel" [(ngModel)]="start" /> <input matEndDate #endControl="ngModel" [(ngModel)]="end" /> </mat-date-range-input> <mat-date-range-picker #dateRangePicker></mat-date-range-picker> <mat-error [ngx-mat-errors]="[startControl, endControl]"></mat-error> </mat-form-field>Run npm run develop to build the library and generate an NPM package. The build artifacts will be stored in the dist/ngx-mat-errors folder.
Run npm start for a dev server. Navigate to http://localhost:4202/. The app will automatically reload if you change any of the source files.