4
votes

I put a recaptcha in a signup form with angular2. I have a controller to match the recaptcha with a validator required.

this.captchaControl = fb.control(false, Validators.required); 
this.userForm = fb.group({
    ...
    captchaControl: this.captchaControl
});

And the value is correctly set to true when the user answer it.

checkReCaptcha(response){
    console.log(this.userForm.valid);
    this.captcha = response;
    this.captchaControl.updateValue(true);
    console.log(this.userForm.valid);
}

The first console log show false, the second print true.

In the submit button, I put the disable function:

<button type="submit" [disabled]="!userForm.valid" class="btn btn-d">Register</button>

But the button stay disable.

How can I trigger the button to check again the validity of userForm?

Update Here is an example of my problem. http://plnkr.co/edit/Rwy6Oc5JEEm7yIJYnxJX?p=preview

When you complete the form, the red button stay disabled even though the form is valid. If you touch any other input form (or the other submit button), the disabled button is updated and becomes available, but it I would expect it to become available when all inputs are defined...

1

1 Answers

4
votes

Looks like a change detection issue caused by code running outside of Angulars zone.

inject ApplicationRef and call tick()` after the value was changed

import {ApplicationRef} from 'angular2/core';

constructor(private appRef:ApplicationRef){} 

checkReCaptcha(response){
    console.log(this.userForm.valid);
    this.captcha = response;
    this.captchaControl.updateValue(true);
    this.appRef.tick();
    console.log(this.userForm.valid);
}

This makes Angular aware that change detection needs to be done.

http://plnkr.co/edit/nYKqtXaaDl69eeL35GTL?p=info

Interestingly no other way of invoking change detection actually worked.

  • setTimeout(...)
  • ChangeDetectorRef.markForCheck()
  • zone.run(...)

didn't cause a new change detection to run. At least when I changed the binding {{userForm.valid}} to {{isUserFormValid()}}, isUserFormValid() wasn't called.

Only this.appRef.tick() made Angular2 reevaluate the binding.