HappySennin
HappySennin

Reputation: 21

How to force form validation before submit?

I need to ensure that every validation in my form is only triggered when a user enters a value and focuses out. That leads to a problem when a value is entered and the user press enter key. The form is submitted even if the value is invalid (but with null value).

Maybe an example will be more helpfull for this situation.

This is the component class:

readonly formGroup: FormGroup;

private constructor() {
  this.formGroup = new FormGroup(
    {
      firstControl: new FormControl(null),
      secondControl: new FormControl(null, Validators.minLength(4))
    },
    { updateOn: "blur" }
  );
}

onSubmit() {
  if (this.formGroup.valid) {
    // some logic here
  }
}

and HTML structure:

<form [formGroup]="formGroup" (ngSubmit)="onSubmit()">
  <label>First control</label>
  <input formControlName="firstControl" />
  <br />
  <label>Second control</label>
  <input formControlName="secondControl" />
  <br />
  <button>Submit</button>
</form>

In this example when the value abc is entered and enter key is pressed on a second control, the form gets submitted.

P.S. I found one solution to add document.activeElement.blur() before if statement in onSubmit() function. This solution is unacceptable in my project.

Upvotes: 2

Views: 7460

Answers (3)

Amer
Amer

Reputation: 6716

You can achieve that by calling FormGroup.markAllAsTouched method if the form is invalid. And if you want to force validate form-group you can call the FormGroup.updateValueAndValidity before checking the valid property, like the following:

onSubmit() {
  this._updateValueAndValidity();

  if (this.formGroup.invalid) {
    this.formGroup.markAllAsTouched(); // will set all the controls as touched 
  } else {
    // some logic here
  }
}

/** Update the value of form-group and validity of it and its descendants */
private _updateValueAndValidity() {
    for (let controlName in this.formGroup.controls) {
        this.formGroup.controls[controlName].updateValueAndValidity();
    }
}

Upvotes: 2

Adam Perea
Adam Perea

Reputation: 399

Instead of using { updateOn: "blur" }, use { updateOn: "change" }.

Also, I see you are using the updateOn option directly within the FormGroup. You can also use it for each FormControl such as:

firstControl: new FormControl(null, updateOn: 'change'),
secondControl: new FormControl(null, Validators.minLength(4), updateOn: 'change')

Upvotes: 0

Harry True
Harry True

Reputation: 1

You can try something like this:

private formGroup!: FormGroup;

    constructor(public fb: FormBuilder) {

    }
    
    ngOnInit(): void {
        this.initForm();
    }

    initForm() {
        this.formGroup = this.fb.group(
            {
                firstControl: new FormControl(null),
                secondControl: new FormControl(null),
                thirdControl: new FormControl(null),
            },
            {
                validators: [
                    this.validateMinLength("secondControl", 4),
                    this.validateMinLength("thirdControl", 6)
                ],
            })

    }

    private validateMinLength(controlName: string, minLength: number) {
        return (formGroup: FormGroup) => {
            const control = formGroup.controls[controlName];

            if (control.value && control.value.length < minLength) {
                control.setErrors({ max: true });
            } else {
                control.setErrors(null);
            }
        };
    }

Upvotes: 0

Related Questions