I have a generic mat-error directive that I've been using to show form errors.
@Component({
selector: '[app-field-error]',
templateUrl: './field-error.component.html',
styleUrls: ['./field-error.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
CommonModule,
MatInputModule,
],
standalone: true
})
export class FieldErrorComponent {
field = input.required<AbstractControl<any, any>>();
fieldName = input.required<string>();
}
And I show the errors on html side accordingly:
<span *ngIf="field().hasError('email')">
Invalid email address.
</span>
Sample usage:
<mat-error app-field-error [field]="contactForm.get('name')" fieldName="Contact Name"/>
After trying zoneless with Angular18, this directive stopped working. I've migrated other components successfully using async pipes and signals accordingly, but in this case I am not sure how this component will get the input updates so that it can show the error messages.
I was able to make this work by subscribing to field statusChanges and calling ChangeDetectorRef.markForCheck. Here is the code:
export class FieldErrorComponent implements OnInit {
field = input.required<AbstractControl<any, any>>();
fieldName = input.required<string>();
constructor(
private cdr: ChangeDetectorRef
) {
}
ngOnInit(): void {
this.field().statusChanges
.pipe(
tap(() => {
this.cdr.markForCheck();
})
)
.subscribe();
}
}