fix(forms): async validator-directives process Observables correctly (#8186)
Closes #/8022
This commit is contained in:
parent
9f00a1b902
commit
eef9512ce6
|
@ -20,7 +20,7 @@ export function normalizeValidator(validator: ValidatorFn | Validator): Validato
|
||||||
|
|
||||||
export function normalizeAsyncValidator(validator: AsyncValidatorFn | Validator): AsyncValidatorFn {
|
export function normalizeAsyncValidator(validator: AsyncValidatorFn | Validator): AsyncValidatorFn {
|
||||||
if ((<Validator>validator).validate !== undefined) {
|
if ((<Validator>validator).validate !== undefined) {
|
||||||
return (c: AbstractControl) => Promise.resolve((<Validator>validator).validate(c));
|
return (c: AbstractControl) => (<Validator>validator).validate(c);
|
||||||
} else {
|
} else {
|
||||||
return <AsyncValidatorFn>validator;
|
return <AsyncValidatorFn>validator;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,11 @@
|
||||||
import {AbstractControl, Control, ControlArray, ControlGroup, Validators} from '@angular/common/src/forms-deprecated';
|
import {AbstractControl, Control, ControlArray, ControlGroup, Validators} from '@angular/common/src/forms-deprecated';
|
||||||
import {fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
|
import {fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
|
||||||
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
|
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
|
||||||
|
import {Observable} from 'rxjs/Observable';
|
||||||
|
|
||||||
import {EventEmitter, ObservableWrapper, TimerWrapper} from '../../src/facade/async';
|
import {EventEmitter, ObservableWrapper, TimerWrapper} from '../../src/facade/async';
|
||||||
import {PromiseWrapper} from '../../src/facade/promise';
|
import {PromiseWrapper} from '../../src/facade/promise';
|
||||||
|
import {normalizeAsyncValidator} from '../../src/forms-deprecated/directives/normalize_validator';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
function validator(key: string, error: any) {
|
function validator(key: string, error: any) {
|
||||||
|
@ -22,6 +24,18 @@ export function main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AsyncValidatorDirective {
|
||||||
|
constructor(private expected: string, private error: any) {}
|
||||||
|
|
||||||
|
validate(c: any): {[key: string]: any;} {
|
||||||
|
return Observable.create((obs: any) => {
|
||||||
|
const error = this.expected !== c.value ? this.error : null;
|
||||||
|
obs.next(error);
|
||||||
|
obs.complete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe('Validators', () => {
|
describe('Validators', () => {
|
||||||
describe('required', () => {
|
describe('required', () => {
|
||||||
it('should error on an empty string',
|
it('should error on an empty string',
|
||||||
|
@ -88,6 +102,17 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should normalize and evaluate async validator-directives correctly', fakeAsync(() => {
|
||||||
|
const c = Validators.composeAsync(
|
||||||
|
[normalizeAsyncValidator(new AsyncValidatorDirective('expected', {'one': true}))]);
|
||||||
|
|
||||||
|
let value: any = null;
|
||||||
|
c(new Control()).then((v: any) => value = v);
|
||||||
|
tick(1);
|
||||||
|
|
||||||
|
expect(value).toEqual({'one': true});
|
||||||
|
}));
|
||||||
|
|
||||||
describe('compose', () => {
|
describe('compose', () => {
|
||||||
it('should return null when given null',
|
it('should return null when given null',
|
||||||
() => { expect(Validators.compose(null)).toBe(null); });
|
() => { expect(Validators.compose(null)).toBe(null); });
|
||||||
|
|
|
@ -20,7 +20,7 @@ export function normalizeValidator(validator: ValidatorFn | Validator): Validato
|
||||||
|
|
||||||
export function normalizeAsyncValidator(validator: AsyncValidatorFn | Validator): AsyncValidatorFn {
|
export function normalizeAsyncValidator(validator: AsyncValidatorFn | Validator): AsyncValidatorFn {
|
||||||
if ((<Validator>validator).validate !== undefined) {
|
if ((<Validator>validator).validate !== undefined) {
|
||||||
return (c: AbstractControl) => Promise.resolve((<Validator>validator).validate(c));
|
return (c: AbstractControl) => (<Validator>validator).validate(c);
|
||||||
} else {
|
} else {
|
||||||
return <AsyncValidatorFn>validator;
|
return <AsyncValidatorFn>validator;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
import {fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
|
import {fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
|
||||||
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
|
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
|
||||||
import {AbstractControl, FormControl, Validators} from '@angular/forms';
|
import {AbstractControl, FormControl, Validators} from '@angular/forms';
|
||||||
|
import {Observable} from 'rxjs/Observable';
|
||||||
|
|
||||||
|
import {normalizeAsyncValidator} from '../src/directives/normalize_validator';
|
||||||
import {EventEmitter, ObservableWrapper, TimerWrapper} from '../src/facade/async';
|
import {EventEmitter, ObservableWrapper, TimerWrapper} from '../src/facade/async';
|
||||||
import {PromiseWrapper} from '../src/facade/promise';
|
import {PromiseWrapper} from '../src/facade/promise';
|
||||||
|
|
||||||
|
@ -22,6 +24,18 @@ export function main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AsyncValidatorDirective {
|
||||||
|
constructor(private expected: string, private error: any) {}
|
||||||
|
|
||||||
|
validate(c: any): {[key: string]: any;} {
|
||||||
|
return Observable.create((obs: any) => {
|
||||||
|
const error = this.expected !== c.value ? this.error : null;
|
||||||
|
obs.next(error);
|
||||||
|
obs.complete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe('Validators', () => {
|
describe('Validators', () => {
|
||||||
describe('required', () => {
|
describe('required', () => {
|
||||||
it('should error on an empty string',
|
it('should error on an empty string',
|
||||||
|
@ -147,12 +161,22 @@ export function main() {
|
||||||
expect(value).toEqual({'one': true, 'two': true});
|
expect(value).toEqual({'one': true, 'two': true});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should normalize and evaluate async validator-directives correctly', fakeAsync(() => {
|
||||||
|
const c = Validators.composeAsync(
|
||||||
|
[normalizeAsyncValidator(new AsyncValidatorDirective('expected', {'one': true}))]);
|
||||||
|
|
||||||
|
let value: any = null;
|
||||||
|
c(new FormControl()).then((v: any) => value = v);
|
||||||
|
tick(1);
|
||||||
|
|
||||||
|
expect(value).toEqual({'one': true});
|
||||||
|
}));
|
||||||
|
|
||||||
it('should return null when no errors', fakeAsync(() => {
|
it('should return null when no errors', fakeAsync(() => {
|
||||||
var c = Validators.composeAsync([asyncValidator('expected', {'one': true})]);
|
var c = Validators.composeAsync([asyncValidator('expected', {'one': true})]);
|
||||||
|
|
||||||
var value: any /** TODO #9100 */ = null;
|
var value: any /** TODO #9100 */ = null;
|
||||||
(<Promise<any>>c(new FormControl('expected'))).then(v => value = v);
|
(<Promise<any>>c(new FormControl('expected'))).then(v => value = v);
|
||||||
|
|
||||||
tick(1);
|
tick(1);
|
||||||
|
|
||||||
expect(value).toEqual(null);
|
expect(value).toEqual(null);
|
||||||
|
|
Loading…
Reference in New Issue