| 
									
										
										
										
											2015-10-29 17:45:24 -07:00
										 |  |  | import {isBlank, isPresent, CONST_EXPR} from 'angular2/src/core/facade/lang'; | 
					
						
							| 
									
										
										
										
											2015-11-05 14:58:24 -08:00
										 |  |  | import {PromiseWrapper} from 'angular2/src/core/facade/promise'; | 
					
						
							| 
									
										
										
										
											2015-11-05 17:18:16 -08:00
										 |  |  | import {ObservableWrapper} from 'angular2/src/core/facade/async'; | 
					
						
							| 
									
										
										
										
											2015-08-28 11:29:19 -07:00
										 |  |  | import {ListWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection'; | 
					
						
							| 
									
										
										
										
											2015-09-03 22:01:36 -07:00
										 |  |  | import {OpaqueToken} from 'angular2/src/core/di'; | 
					
						
							| 
									
										
										
										
											2015-02-11 11:10:31 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-09 17:41:49 +01:00
										 |  |  | import * as modelModule from './model'; | 
					
						
							| 
									
										
										
										
											2015-02-11 11:10:31 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 12:59:56 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Providers for validators to be used for {@link Control}s in a form. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Provide this using `multi: true` to add validators. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ### Example | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```typescript
 | 
					
						
							|  |  |  |  * var providers = [ | 
					
						
							|  |  |  |  *   new Provider(NG_VALIDATORS, {useValue: myValidator, multi: true}) | 
					
						
							|  |  |  |  * ]; | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-09-03 08:14:51 -07:00
										 |  |  | export const NG_VALIDATORS: OpaqueToken = CONST_EXPR(new OpaqueToken("NgValidators")); | 
					
						
							| 
									
										
										
										
											2015-11-02 09:59:40 -08:00
										 |  |  | export const NG_ASYNC_VALIDATORS: OpaqueToken = CONST_EXPR(new OpaqueToken("NgAsyncValidators")); | 
					
						
							| 
									
										
										
										
											2015-09-02 10:24:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-31 22:47:11 +00:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2015-04-10 11:15:01 -07:00
										 |  |  |  * Provides a set of validators used by form controls. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-09-29 12:59:56 -07:00
										 |  |  |  * A validator is a function that processes a {@link Control} or collection of | 
					
						
							|  |  |  |  * controls and returns a {@link StringMap} of errors. A null map means that | 
					
						
							|  |  |  |  * validation has passed. | 
					
						
							| 
									
										
										
										
											2015-04-10 11:15:01 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-09-29 12:59:56 -07:00
										 |  |  |  * # Example | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```typescript
 | 
					
						
							| 
									
										
										
										
											2015-04-10 11:15:01 -07:00
										 |  |  |  * var loginControl = new Control("", Validators.required) | 
					
						
							|  |  |  |  * ```
 | 
					
						
							| 
									
										
										
										
											2015-03-31 22:47:11 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-03-19 14:21:40 -07:00
										 |  |  | export class Validators { | 
					
						
							| 
									
										
										
										
											2015-09-29 12:59:56 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Validator that requires controls to have a non-empty value. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2015-10-02 16:47:54 -07:00
										 |  |  |   static required(control: modelModule.Control): {[key: string]: boolean} { | 
					
						
							| 
									
										
										
										
											2015-09-01 20:59:43 -07:00
										 |  |  |     return isBlank(control.value) || control.value == "" ? {"required": true} : null; | 
					
						
							| 
									
										
										
										
											2015-03-19 14:21:40 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-02-11 11:10:31 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 12:59:56 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Validator that requires controls to have a value of a minimum length. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2015-10-13 14:38:13 -07:00
										 |  |  |   static minLength(minLength: number): Function { | 
					
						
							|  |  |  |     return (control: modelModule.Control): {[key: string]: any} => { | 
					
						
							|  |  |  |       if (isPresent(Validators.required(control))) return null; | 
					
						
							|  |  |  |       var v: string = control.value; | 
					
						
							|  |  |  |       return v.length < minLength ? | 
					
						
							|  |  |  |                  {"minlength": {"requiredLength": minLength, "actualLength": v.length}} : | 
					
						
							|  |  |  |                  null; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 12:59:56 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Validator that requires controls to have a value of a maximum length. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2015-10-13 14:38:13 -07:00
										 |  |  |   static maxLength(maxLength: number): Function { | 
					
						
							|  |  |  |     return (control: modelModule.Control): {[key: string]: any} => { | 
					
						
							|  |  |  |       if (isPresent(Validators.required(control))) return null; | 
					
						
							|  |  |  |       var v: string = control.value; | 
					
						
							|  |  |  |       return v.length > maxLength ? | 
					
						
							|  |  |  |                  {"maxlength": {"requiredLength": maxLength, "actualLength": v.length}} : | 
					
						
							|  |  |  |                  null; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 12:59:56 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * No-op validator. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2015-10-02 16:47:54 -07:00
										 |  |  |   static nullValidator(c: any): {[key: string]: boolean} { return null; } | 
					
						
							| 
									
										
										
										
											2015-02-11 11:10:31 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 12:59:56 -07:00
										 |  |  |   /** | 
					
						
							|  |  |  |    * Compose multiple validators into a single function that returns the union | 
					
						
							|  |  |  |    * of the individual error maps. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2015-08-28 11:29:19 -07:00
										 |  |  |   static compose(validators: Function[]): Function { | 
					
						
							| 
									
										
										
										
											2015-11-02 09:59:40 -08:00
										 |  |  |     if (isBlank(validators)) return null; | 
					
						
							|  |  |  |     var presentValidators = ListWrapper.filter(validators, isPresent); | 
					
						
							|  |  |  |     if (presentValidators.length == 0) return null; | 
					
						
							| 
									
										
										
										
											2015-09-02 10:24:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												feat(validators): Allow errors at both the group/array level or their children
Allow ControlGroups and ControlArrays to contain errors from their level, and
errors from their children. [Design Doc](https://docs.google.com/document/d/1EnJ3-_iFpVKFz1ifN1LkXSGQ7h3A72OQGry2g8eo7IA/edit?pli=1#heading=h.j53rt81eegm4)
BREAKING CHANGE: errors format has changed from validators. Now errors from
a control or an array's children are prefixed with 'controls' while errors
from the object itself are left at the root level.
Example:
Given a Control group as follows:
var group = new ControlGroup({
  login: new Control("", required),
  password: new Control("", required),
  passwordConfirm: new Control("", required)
});
Before:
group.errors
{
  login: {required: true},
  password: {required: true},
  passwordConfirm: {required: true},
}
After:
group.errors
{
  controls: {
    login: {required: true},
    password: {required: true},
    passwordConfirm: {required: true},
  }
}
											
										 
											2015-10-16 16:13:14 -07:00
										 |  |  |     return function(control: modelModule.AbstractControl) { | 
					
						
							| 
									
										
										
										
											2015-11-02 09:59:40 -08:00
										 |  |  |       return _mergeErrors(_executeValidators(control, presentValidators)); | 
					
						
							| 
									
										
										
										
											2015-07-15 12:12:23 -07:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2015-03-19 14:21:40 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-02 09:59:40 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   static composeAsync(validators: Function[]): Function { | 
					
						
							|  |  |  |     if (isBlank(validators)) return null; | 
					
						
							| 
									
										
										
										
											2015-11-05 17:18:16 -08:00
										 |  |  |     let presentValidators = ListWrapper.filter(validators, isPresent); | 
					
						
							| 
									
										
										
										
											2015-11-02 09:59:40 -08:00
										 |  |  |     if (presentValidators.length == 0) return null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return function(control: modelModule.AbstractControl) { | 
					
						
							| 
									
										
										
										
											2015-11-05 17:18:16 -08:00
										 |  |  |       let promises = _executeValidators(control, presentValidators).map(_convertToPromise); | 
					
						
							|  |  |  |       return PromiseWrapper.all(promises).then(_mergeErrors); | 
					
						
							| 
									
										
										
										
											2015-11-02 09:59:40 -08:00
										 |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 17:18:16 -08:00
										 |  |  | function _convertToPromise(obj: any): any { | 
					
						
							|  |  |  |   return PromiseWrapper.isPromise(obj) ? obj : ObservableWrapper.toPromise(obj); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-02 09:59:40 -08:00
										 |  |  | function _executeValidators(control: modelModule.AbstractControl, validators: Function[]): any[] { | 
					
						
							|  |  |  |   return validators.map(v => v(control)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function _mergeErrors(arrayOfErrors: any[]): {[key: string]: any} { | 
					
						
							|  |  |  |   var res = ListWrapper.reduce(arrayOfErrors, (res, errors) => { | 
					
						
							|  |  |  |     return isPresent(errors) ? StringMapWrapper.merge(<any>res, <any>errors) : res; | 
					
						
							|  |  |  |   }, {}); | 
					
						
							|  |  |  |   return StringMapWrapper.isEmpty(res) ? null : res; | 
					
						
							| 
									
										
										
										
											2015-02-11 11:10:31 -08:00
										 |  |  | } |