Display mat-form-field error message before control is touched

Viewed 1626

This question has a Stackblitz; stackblitz.com/edit/yz1dhz.

How can mat-form-field validation error messages be rendered when a component loads and before the user has touched the control?

class AppComponent implements OnInit {
  form: FormGroup;

  constructor(private readonly fb: FormBuilder) {
    // Create a form in an invalid state.
    this.form = this.fb.group({
      a: this.fb.control(null, [Validators.required])
    });
  }

  ngOnInit() {
    // This does do what I had hoped.
    this.form.updateValueAndValidity();
  }
}

That code creates a form which is immediately invalid. I expected <mat-error> to show:

<form [formGroup]="form">
    <mat-form-field>
        <mat-select formControlName="a">
            <mat-option>Foo</mat-option>
            <mat-option>Bar</mat-option>
            <mat-option>Baz</mat-option>
        </mat-select>
    <mat-hint>I am a hint.</mat-hint>
    <mat-error>{{ form.controls['a'].errors | json }}</mat-error>
    </mat-form-field>
</form>

But instead the <mat-hint> is displayed.

enter image description here

2 Answers

You can force it that way

this.form.get('a').markAsTouched();

or you can mark all controls as touched

this.form.markAllAsTouched();

you can change the status of a form control using markAsTouched, markAllAsTouched, markAsUntouched, markAsDirty, markAsPristine, markAsPending...

A cleaner solution may be to use an errorStateMatcher. From the link (emphasis mine):

By default, these error messages are shown when the control is invalid and either the user has interacted with (touched) the element or the parent form has been submitted. If you wish to override this behavior (e.g. to show the error as soon as the invalid control is dirty or when a parent form group is invalid), you can use the errorStateMatcher property of the matInput.

There is an example in that page, that you can tweak to show the error as soon as the control becomes invalid (without having been touched)

This looks like more code than using the accepted response, but it doesn't mess with the "touched" status of your control.

Related