angularangular-materialng-template

mat-form-field is displayed with the error cue even though it's pristine and untouched when declared in ng-template in a different component


Default angular/ angular material behavior is not to overwhelm the user with error cues when a control is pristine and untouched (i.e. a control is shown for the first time and is invalid but the user hasn't interacted with it yet). For some reason, when a mat-form-field is declared as an ng-template and used via ng-container/ngTemplateOutlet, it's highlighted even though it has ng-untouched and ng-pristine. This is only reproducible when ng-template is declared in a different component.

Here is an example: https://stackblitz.com/edit/angular-16-material-starter-yvqsck?file=src%2Fapp%2Fapp.component.html enter image description here

I'm using mat-stepper with two steps:

Step 1 Has TemplateStepComponent component that declares ng-template with mat-form-field. this template is saved in TemplateStepComponent.template static field.

Step 2 has three mat-form-field which are bound to the same item: FormControl with Validators.required.

  1. Is rendered using ngTemplateOutlet and using a TemplateRef declared in the previous step - TemplateStepComponent.template. Expected: no error, Actual: highlighted even though it's untouched and pristine
  2. Is similar to the first one but the ng-template and ng-container/ngTemplateOutlet are inlined. Behaves as expected.
  3. The third one is a regular mat-form-field and behaves and is expected.

Not really sure why #1 doesn't work as expected even though it's pristine and untouched. It definitely has to do with the fact that the template is declared outside of the current component but I don't understand why it matters.

I found that usage of <form> with <button type=submit> can trigger this behavior (Angular Material form control highlighted in red even though pristine) but I don't use forms nor the fix helps in my case.


Solution

  • As @Eliseo, pointed out mat-stepper is the culprit: when we navigate away from the step where template is defined, mat-stepper marks the mat-form-field as invalid ignoring bound FormControl. I created a better example to point this out: enter image description here Source: https://stackblitz.com/edit/angular-16-material-starter-yvqsck?file=README.md

    It's not exactly clear to me how mat-stepper marks the mat-form-field as invalid inside of the template