0
votes

I've got a reactive form with nested formgroups with some form controls that have required validators.

It seems the validation only occurs when a user inputs values into the form. If the form is submitted with no user interaction, empty textboxes with a required validator show as valid. Is this a normal behavior of angular forms? Am I missing something?

Thanks

Pete

html template:

<form [formGroup]="ticketMarkForm" (ngSubmit)="submitTicket()">
  ..
   <div formGroupName ="systemForm">
     <mat-form-field appearance="outline">
      <mat-label>Pipe Length (Ft):</mat-label>
      <input matInput type="number" required formControlName="pipeLength">
     </mat-form-field>
</div>
 ..
 <button type="submit" mat-stroked-button>Submit</button>
</form>

component typescript:

export class MtMarkFormComponent implements OnInit {
..
ticketMarkForm: FormGroup;
...
constructor(private checkService: MTMarkFormCheckService) { }
 ngOnInit(): void {
 //forms
 this.ticketMarkForm = new FormGroup({
  systemForm: new FormGroup({
    ...
   pipeDiameter: new FormControl(Validators.required),
   ...
  })
  });

}
submitTicket() {
   let pipeDiam:any=this.ticketMarkForm.get('systemForm').get('pipeDiameter');
   this.checkService.CheckRequiredValid(pipeDiam);
   }
}

Service to check form typescript:

export class MTMarkFormCheckService {
 CheckRequiredValid(fc: FormControl) {
        if (fc.invalid) {//if the control is left blank/untouched evaluates to valid.  I've also 
  tried to mark the control as dirty (fc.markAsDirty()) but same result
            alert("invalid");
         }
         else {
           alert("valid");
        }
 }
2

2 Answers

1
votes

It is default Angular behavior. You have to define custom error state matcher like this.

import {FormControl, FormGroupDirective, NgForm} from '@angular/forms';
import {ErrorStateMatcher} from '@angular/material/core';

export class CustomErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null | undefined, form: FormGroupDirective | NgForm | null): boolean {
    if (control == null) {
      return false;
    }
    return control.invalid;
  }
}

ts :

export class MtMarkFormComponent implements OnInit {
   :
  public esm = new CustomErrorStateMatcher();
   :
}

html :

<input matInput type="number" required formControlName="pipeLength" [errorStateMatcher]="esm">
1
votes

This statement is not very clear but will try to explore

empty textboxes with a required validator show as valid

I have tried to replicate the problem you have described in this Stackblitz demo but I am getting different conclusions.

Empty textboxes with required validators will be return false for the valid property

It is important to note that validations on the form will not show until the form is touched

In the demo I have commented out the line // this.ticketMarkForm.markAllAsTouched(). If this is uncommented, validations will show on the form

By default angular will call (ngSubmit)='someFunction()' (see Angularjs prevent form submission when input validation fails) but the form status will be invalid.

If you try to submit the form in the demo You will notice that the console log shows false