angular18zoneless

Custom mat-error directive not working with Angular 18 zoneless


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.


Solution

  • 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();
     }
    
    }