1

I am trying to validate a field with synchronous and async validation. There is a problem occuring when the field changes before the async validation ends. If after changing the validation returns an error (the field is invalid), but there is still an async validation running (from a previous value), and the async validation return after that, the field becomes valid again, but should stay invalid.


Plunker

I created a plunker to show this occurrence: http://plnkr.co/edit/q0jttO

The plunker code that create the FormGroup (using the new forms) with the validators is:

this.formGroup = formBuilder.group({
    id: [''],
    name: [
        '', 
        (c: AbstractControl) => (c.value != null && c.value.length >= 3) ? null : {
            key: 'name_minlength', 
            msg: 'The name must have at least 3 characters'
        }
    ],
    email: [
        '', 
        (c: AbstractControl) => {
            if (c.value != null && c.value.length !== 4) {
                console.log('sync - success -> ' + c.value);

                return null; // OK
            } else {
                console.log('sync - error -> ' + c.value);

                return {
                    key: 'email_4char', 
                    msg: 'The email must not have 4 characters'
                };
            }
        },
        (c: AbstractControl) => new Promise(
            resolve => {
                console.log('async started -> ' + c.value);

                setTimeout(() => {
                    if (c.value !== 'aaa') {
                        console.log('async ended - success -> ' + c.value);

                        resolve(null); //OK
                    } else {
                        console.log('async ended - error -> ' + c.value);

                        resolve({
                            key: 'email_aaa', 
                            msg: 'The email must be different than "aaa"'
                        });
                    }
                }, 2000)
            }
        )
    ]
});

I don't know if this something that I forgot to do or that I did wrong, or if it's a problem of angular 2 (after all, it's still in beta).


Steps to Simulate

I made the steps to simulate this problem simple making the validation give an async error if aaa is typed and a sync error if aaaa is typed.

You can reproduce these steps in the plunker (you can see the logs of the validations in the browser console):

  1. Typing aa in the email field (the field is valid).
  2. Then you type another a and wait for the validation (the async validation will show an error).
  3. Then type another a (becoming aaaa), and the sync validation will show an error (until now it's alright, but wait).
  4. Delete the last 2 as to become aa again.
  5. Type 1 a and then another a before the validation end.

The error message from the validation with aaaa will show, but then the async validation will end and the message will disappear.


Logs

Sync Validation where email must not have 4 characters (just for example purposes) and an error message must be shown:

1) Shows the error (console logs when typing slowly):

sync - success -> aaa
async started -> aaa
async ended - error -> aaa
sync - error -> aaaa

2) Shows the error, but then hide it after the previous async call return with success (console logs when typing faster):

sync - success -> aaa
async started -> aaa
sync - error -> aaaa
async ended - success -> aaaa

It's not only the error not showing, but the class also stays as ng-valid (should be invalid, the error is not shown because of it).

This also occurs if I change the async validator to only return valid (resolve with null), because what happens is that the async return from the previous value changes the validation result of the last value typed (this shouldn't happen; only the validations related to the last value should define its validity):

resolve => {
    console.log('async started -> ' + c.value);

    setTimeout(() => {
        console.log('async ended -> ' + c.value);
        resolve(null); //OK
    }, 2000)
}

Is there a way to make the field stay invalid even if the async validation from a previous value ends after a validation error from the last value typed?

Lucas Basquerotto
  • 7,260
  • 2
  • 47
  • 61
  • I'm running into the same issue, did you ever figure this out? – jparram Jan 26 '17 at 19:15
  • @jparram nope :S I'm not using the async validation at the moment. What would be validated asynchronously is validated when I sent the data to the server (it would be validated in this case anyway, the async would be more for the user experience). – Lucas Basquerotto Jan 27 '17 at 19:44
  • Here is a functional answer: https://stackoverflow.com/questions/36235446/angular2-template-driven-async-validator – Belter Oct 11 '17 at 09:35

0 Answers0