General: asynchronous validation in angular2

From the evening of the couple I played with form confirmation in augular2.

All of the main cases were easy to implement, and they work great, but I adhere to asynchronous validation. I created a very small example http://plnkr.co/edit/Xo8xwJjhlHkXrunzS8ZE and it did not work.

According to the test, “it should trigger an event after the status has been updated to the expected one” from model_spec.ts. Registration through the creation of a control group assumes to work along the way.

builder.group({login: ["",Validators.required,validationFuctionWhichReturnsPromise]

I spent the whole evening discovering that this code was released in alfa-46 (and I used alfa-45), and after updating the updates, asynchronous checking started. This feature is very fresh and not fully documented, but

(for those who have not tried it yet). Basically, an asynchronous validator is a function that takes a Control argument and returns a promise that confirms the result of the check. There are two ways to register a validator. 1) the one I used in my example, and 2) as a directive that provides validators via NG_ASYNC_VALIDATORS (see UniqLoginValidator and NgFormControl to see how this works). You can create more than one validator (not yet tested, but the functions for this are in the code, see https://github.com/angular/angular/commit/cf449dd ).

, . . model.fe . , , ;) , angular 1, .

:

  • debounce ? , ( , angular). , angular?

debounce ( underscorejs), , angular .

, RxJs , , , debounce , . model.ts , , . obs (Observable) .

  1. - , ?

angular2

PS , , https://github.com/angular/angular/issues/1068

+4
2

, :

import {Component} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import {Observer} from 'rxjs/Observer';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import {Control} from 'angular2/common';

export class AsyncValidator {
_validate;

constructor(validator: (control: Control) => any, debounceTime = 1000) {
    let source: any = new Observable((observer: Observer<Control>) => {
        this._validate = (control) => observer.next(control);
    });

    source.debounceTime(debounceTime)
        .distinctUntilChanged(null, (x) => x.control.value)
        .map(x => { return { promise: validator(x.control), resolver: x.promiseResolver }; })
        .subscribe(
            (x) => x.promise.then(resultValue => x.resolver(resultValue),
            (e) => { console.log('async validator error: %s', e); }));
}

private _getValidator() {
    return (control) => {
        let promiseResolver;
        let p = new Promise((resolve) => {
            promiseResolver = resolve;
        });
        this._validate({ control: control, promiseResolver: promiseResolver });
        return p;
    };
}

static debounce(validator: (control: Control) => any, debounceTime = 400) {
    var asyncValidator = new this(validator, debounceTime);
    return asyncValidator._getValidator();
}
}

, , , , :

AsyncValidator.debounce(control => this.asyncValidator(control));

:

export class AppComponent {
form: ControlGroup;

constructor(private _formBuilder: FormBuilder) {
    var validator = AsyncValidator.debounce(control => this.asyncValidator(control));

    this.form = _formBuilder.group({
        name: ['', Validators.required, validator],
    });
}

asyncValidator(control): any {
    let p = new Promise(resolve => {
        // get from server information need to validate control

        if (control.value === 'valid value') {
            resolve(null);
        } else {

            resolve({
                asyncValidator: {
                    valid: false
                }
            });
        }
    });
    return p;
}
}
+9

angular , debouncing, switchMapping :

https://github.com/angular/angular/issues/6895

( )

class AsyncValidator{
  private validatorInput: Subject<string>;
  private validatorChain: Observable<any>;
  constructor(service: ManageUsersService) {
    this.validatorInput = new Subject();
    this.validatorChain = this.validatorInput
      .debounceTime(400)
      .distinctUntilChanged()
      .switchMap(value => service.findUsersByName(value)
                                 .map(() => ({error: 'Error'})) //example of failed validation
                                 .catch(() => Observable.of(null))) //example of successful validation
      .do(v => console.log('mapped', v))
      .share()
      .take(1);
  }

  validate = (control: AbstractControl) => {
    // An immediate timeout is set because the next has to occur after the 
    // validator chain is subscribed to.
    setTimeout(() => this.validatorInput.next(control.value), 0);
    return this.validatorChain;
}

:

this.createUserForm = fb.group({
        login: [ null, 
                 Validators.required, 
                 new AsyncValidator(userService).validate
               ],
      });
    }
+2

Source: https://habr.com/ru/post/1616508/


All Articles