Search code examples
formsangularvalidation

How to force Angular 2 to re-check validator?


I have a simple login form written in Angular 2 reactive (data-driven) template. It's working perfectly but when I refresh the page and browser fills e-mail+password (autocomplete), my form's valid property seems false.

But when I press any key or click anywhere in my page while form is invalid, angular updates some states (I guess) and my form become valid.

How can I trigger that state? How can I say angular "Hey, check my form again."? I can't trigger my own validation script because some validation messages are alerts. If I do this, when user open this page, he/she will see these alerts.

I remember, I use trigger('input') trick to update ng-model.


Solution

  • updateValueAndValidity() is what you are looking for. The document is here: AbstractControl. It can force recalculate the value and validation status of the control.

    Here's a demo:

    form.component.ts

    export class FormComponent implements OnInit {
      myform: FormGroup;
    
      // explicit validation of each field
      emailValid: AbstractControl;
      passwordValid: AbstractControl;
    
      constructor(private fb: FormBuilder) {
        this.myform = fb.group({
          'email': ['', Validators.required],
          'password': ['', Validators.required],
        });
    
        this.emailValid = this.myform.controls['email'];
        this.passwordValid = this.myform.controls['password'];
      }
    
        ngOnInit() {
            this.myform.get('email').valueChanges.subscribe(()=>forceValidAgain());
            this.myform.get('password').valueChanges.subscribe(()=>forceValidAgain());
        }
    
      forceValidAgain(){
        this.emailValid.updateValueAndValidity();
        this.passwordValid.updateValueAndValidity();
      }
    }
    

    form.component.html

    <form [formGroup]="myform" (ngSubmit)="onSubmit(myform.value)">
      <div class="form-group">
        <label for="email">Email</label>
        <input type="email"
               class="form-control"
               id="email"
               name="email"
               [formControl]="myform.controls['email']"
               [ngClass]="{'is-invalid': !emailValid.valid && emailValid.touched }">
        <div
          class="invalid-feedback"
          *ngIf="emailValid.hasError('required')">
          This field is required
        </div>
      </div>
    
      <div class="form-group">
        <label for="password">Password</label>
        <input type="password"
               class="form-control"
               id="password"
               name="password"
               [formControl]="myform.controls['password']"
               [ngClass]="{'is-invalid': !passwordValid.valid && passwordValid.touched}">
        <div
          class="invalid-feedback"
          *ngIf="passwordValid.hasError('required')">
          This field is required
        </div>
      </div>
    </form>