@@ -59,8 +59,9 @@ export abstract class AbstractControl {
5959 private _pristine : boolean = true ;
6060 private _touched : boolean = false ;
6161 private _parent : ControlGroup | ControlArray ;
62+ private _asyncValidationSubscription ;
6263
63- constructor ( public validator : Function ) { }
64+ constructor ( public validator : Function , public asyncValidator : Function ) { }
6465
6566 get value ( ) : any { return this . _value ; }
6667
@@ -119,10 +120,14 @@ export abstract class AbstractControl {
119120
120121 this . _updateValue ( ) ;
121122
122- this . _errors = this . validator ( this ) ;
123+ this . _errors = this . _runValidator ( ) ;
123124 this . _controlsErrors = this . _calculateControlsErrors ( ) ;
124125 this . _status = this . _calculateStatus ( ) ;
125126
127+ if ( this . _status == VALID || this . _status == PENDING ) {
128+ this . _runAsyncValidator ( ) ;
129+ }
130+
126131 if ( emitEvent ) {
127132 ObservableWrapper . callNext ( this . _valueChanges , this . _value ) ;
128133 }
@@ -132,6 +137,23 @@ export abstract class AbstractControl {
132137 }
133138 }
134139
140+ private _runValidator ( ) { return isPresent ( this . validator ) ? this . validator ( this ) : null ; }
141+
142+ private _runAsyncValidator ( ) {
143+ if ( isPresent ( this . asyncValidator ) ) {
144+ this . _status = PENDING ;
145+ this . _cancelExistingSubscription ( ) ;
146+ this . _asyncValidationSubscription =
147+ ObservableWrapper . subscribe ( this . asyncValidator ( this ) , res => this . setErrors ( res ) ) ;
148+ }
149+ }
150+
151+ private _cancelExistingSubscription ( ) : void {
152+ if ( isPresent ( this . _asyncValidationSubscription ) ) {
153+ ObservableWrapper . dispose ( this . _asyncValidationSubscription ) ;
154+ }
155+ }
156+
135157 /**
136158 * Sets errors on a control.
137159 *
@@ -190,13 +212,18 @@ export abstract class AbstractControl {
190212 }
191213
192214 private _calculateStatus ( ) : string {
193- return isPresent ( this . _errors ) || isPresent ( this . _controlsErrors ) ? INVALID : VALID ;
215+ if ( isPresent ( this . _errors ) ) return INVALID ;
216+ if ( this . _anyControlsHaveStatus ( PENDING ) ) return PENDING ;
217+ if ( this . _anyControlsHaveStatus ( INVALID ) ) return INVALID ;
218+ return VALID ;
194219 }
195220
196221 /** @internal */
197222 abstract _updateValue ( ) : void ;
198223 /** @internal */
199224 abstract _calculateControlsErrors ( ) : any ;
225+ /** @internal */
226+ abstract _anyControlsHaveStatus ( status : string ) : boolean ;
200227}
201228
202229/**
@@ -219,8 +246,8 @@ export class Control extends AbstractControl {
219246 /** @internal */
220247 _onChange : Function ;
221248
222- constructor ( value : any = null , validator : Function = Validators . nullValidator ) {
223- super ( validator ) ;
249+ constructor ( value : any = null , validator : Function = null , asyncValidator : Function = null ) {
250+ super ( validator , asyncValidator ) ;
224251 this . _value = value ;
225252 this . updateValueAndValidity ( { onlySelf : true , emitEvent : false } ) ;
226253 this . _valueChanges = new EventEmitter ( ) ;
@@ -259,6 +286,11 @@ export class Control extends AbstractControl {
259286 */
260287 _calculateControlsErrors ( ) { return null ; }
261288
289+ /**
290+ * @internal
291+ */
292+ _anyControlsHaveStatus ( status : string ) : boolean { return false ; }
293+
262294 /**
263295 * Register a listener for change events.
264296 */
@@ -282,9 +314,9 @@ export class ControlGroup extends AbstractControl {
282314 private _optionals : { [ key : string ] : boolean } ;
283315
284316 constructor ( public controls : { [ key : string ] : AbstractControl } ,
285- optionals : { [ key : string ] : boolean } = null ,
286- validator : Function = Validators . nullValidator ) {
287- super ( validator ) ;
317+ optionals : { [ key : string ] : boolean } = null , validator : Function = null ,
318+ asyncValidator : Function = null ) {
319+ super ( validator , asyncValidator ) ;
288320 this . _optionals = isPresent ( optionals ) ? optionals : { } ;
289321 this . _valueChanges = new EventEmitter ( ) ;
290322
@@ -348,6 +380,15 @@ export class ControlGroup extends AbstractControl {
348380 return StringMapWrapper . isEmpty ( res ) ? null : res ;
349381 }
350382
383+ /** @internal */
384+ _anyControlsHaveStatus ( status : string ) : boolean {
385+ var res = false ;
386+ StringMapWrapper . forEach ( this . controls , ( control , name ) => {
387+ res = res || ( this . contains ( name ) && control . status == status ) ;
388+ } ) ;
389+ return res ;
390+ }
391+
351392 /** @internal */
352393 _reduceValue ( ) {
353394 return this . _reduceChildren ( { } , ( acc , control , name ) => {
@@ -396,8 +437,9 @@ export class ControlGroup extends AbstractControl {
396437 * ### Example ([live demo](http://plnkr.co/edit/23DESOpbNnBpBHZt1BR4?p=preview))
397438 */
398439export class ControlArray extends AbstractControl {
399- constructor ( public controls : AbstractControl [ ] , validator : Function = Validators . nullValidator ) {
400- super ( validator ) ;
440+ constructor ( public controls : AbstractControl [ ] , validator : Function = null ,
441+ asyncValidator : Function = null ) {
442+ super ( validator , asyncValidator ) ;
401443
402444 this . _valueChanges = new EventEmitter ( ) ;
403445
@@ -457,6 +499,12 @@ export class ControlArray extends AbstractControl {
457499 return anyErrors ? res : null ;
458500 }
459501
502+ /** @internal */
503+ _anyControlsHaveStatus ( status : string ) : boolean {
504+ return ListWrapper . any ( this . controls , c => c . status == status ) ;
505+ }
506+
507+
460508 /** @internal */
461509 _setParentForControls ( ) : void {
462510 this . controls . forEach ( ( control ) => { control . setParent ( this ) ; } ) ;
0 commit comments