Keywords: Angular | Material | Form Validation | ErrorStateMatcher | Button Click
Abstract: This article explores how to programmatically trigger Angular Material's mat-error display upon button click, focusing on the ErrorStateMatcher approach for template-driven forms, with comprehensive code examples and analysis of alternative methods like markAsTouched() and markAllAsTouched().
In Angular Material applications, form validation is essential for data integrity. By default, the <mat-error> component relies on user interactions, such as losing focus from an input field, to display error messages. However, developers often need to trigger error display programmatically, for instance, upon a button click to enforce validation. This article delves into how to achieve this using the ErrorStateMatcher interface and compares it with other techniques.
Core Mechanism of ErrorStateMatcher
ErrorStateMatcher is an interface provided by Angular Material that allows customizing the logic for determining error states. Its key method is isErrorState, which takes a FormControl and parent form as parameters and returns a boolean indicating whether errors should be shown. The default behavior only shows errors when a control is invalid and either touched or dirty, but by overriding this method, conditions can be extended to include button click events.
To implement, first create a custom ErrorStateMatcher class. For example, define a class that shows errors whenever the control is invalid, ignoring the touched or dirty state:
import { ErrorStateMatcher } from '@angular/material/core';
import { FormControl, FormGroupDirective, NgForm } from '@angular/forms';
export class CustomErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
return !!(control && control.invalid);
}
}Instantiate this class in the component and bind it to the errorStateMatcher property of matInput:
matcher = new CustomErrorStateMatcher();In the HTML template, update the input field to use the matcher:
<mat-form-field>
<input matInput placeholder="Due Date" name="dueDate" [(ngModel)]="dueDate" [formControl]="dueDateValidator" [errorStateMatcher]="matcher" required>
<mat-error *ngIf="dueDateValidator.invalid">Due Date is required for Tasks</mat-error>
</mat-form-field>With this configuration, when a button click event occurs, ensuring the control's invalid state is true will immediately display the error message without relying on user interaction.
Alternative Implementation Methods
Beyond ErrorStateMatcher, Angular's form API offers direct methods to manipulate control states. For example, using the markAsTouched() method on a FormControl: call this.dueDateValidator.markAsTouched() in the button click event handler to simulate user touch and trigger error display. This approach is suitable for simple scenarios but may conflict with other validation logic.
For Angular 8 and above, the markAllAsTouched() method on FormGroup is more powerful, as it marks the form and all its child controls as touched, ideal for batch validation. However, this method can over-trigger errors and should be used cautiously.
In summary, ErrorStateMatcher provides the most flexible and controlled approach by decoupling error display logic from user interactions, supporting complex validation needs. In practice, it is recommended to choose a solution based on specific scenarios and ensure code maintainability.