chore: fix DDC errors / warnings

Closes #7195
This commit is contained in:
Misko Hevery
2016-02-19 11:49:31 -08:00
committed by Miško Hevery
parent ef9e40e82b
commit 14f0e9ada8
88 changed files with 527 additions and 468 deletions
@@ -1,6 +1,7 @@
import {ControlValueAccessor} from './control_value_accessor';
import {AbstractControlDirective} from './abstract_control_directive';
import {unimplemented} from 'angular2/src/facade/exceptions';
import {AsyncValidatorFn, ValidatorFn} from './validators';
/**
* A base class that all control directive extend.
@@ -12,8 +13,8 @@ export abstract class NgControl extends AbstractControlDirective {
name: string = null;
valueAccessor: ControlValueAccessor = null;
get validator(): Function { return unimplemented(); }
get asyncValidator(): Function { return unimplemented(); }
get validator(): ValidatorFn { return <ValidatorFn>unimplemented(); }
get asyncValidator(): AsyncValidatorFn { return <AsyncValidatorFn>unimplemented(); }
abstract viewToModelUpdate(newValue: any): void;
}
@@ -16,7 +16,8 @@ import {ControlContainer} from './control_container';
import {controlPath, composeValidators, composeAsyncValidators} from './shared';
import {ControlGroup} from '../model';
import {Form} from './form_interface';
import {Validators, NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators';
import {AsyncValidatorFn, ValidatorFn} from './validators';
const controlGroupProvider =
CONST_EXPR(new Provider(ControlContainer, {useExisting: forwardRef(() => NgControlGroup)}));
@@ -106,7 +107,7 @@ export class NgControlGroup extends ControlContainer implements OnInit,
*/
get formDirective(): Form { return this._parent.formDirective; }
get validator(): Function { return composeValidators(this._validators); }
get validator(): ValidatorFn { return composeValidators(this._validators); }
get asyncValidator(): Function { return composeAsyncValidators(this._asyncValidators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); }
}
@@ -27,7 +27,8 @@ import {
selectValueAccessor
} from './shared';
import {Control} from '../model';
import {Validators, NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators';
import {ValidatorFn, AsyncValidatorFn} from './validators';
const controlNameBinding =
@@ -136,9 +137,9 @@ export class NgControlName extends NgControl implements OnChanges,
get formDirective(): any { return this._parent.formDirective; }
get validator(): Function { return composeValidators(this._validators); }
get validator(): ValidatorFn { return composeValidators(this._validators); }
get asyncValidator(): Function { return composeAsyncValidators(this._asyncValidators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); }
get control(): Control { return this.formDirective.getControl(this); }
}
@@ -23,6 +23,7 @@ import {
isPropertyUpdated,
selectValueAccessor
} from './shared';
import {ValidatorFn, AsyncValidatorFn} from './validators';
const formControlBinding =
CONST_EXPR(new Provider(NgControl, {useExisting: forwardRef(() => NgFormControl)}));
@@ -110,9 +111,9 @@ export class NgFormControl extends NgControl implements OnChanges {
get path(): string[] { return []; }
get validator(): Function { return composeValidators(this._validators); }
get validator(): ValidatorFn { return composeValidators(this._validators); }
get asyncValidator(): Function { return composeAsyncValidators(this._asyncValidators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); }
get control(): Control { return this.form; }
@@ -3,7 +3,6 @@ import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
import {
OnChanges,
SimpleChange,
Query,
Directive,
forwardRef,
Provider,
@@ -14,7 +13,7 @@ import {
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {NgControl} from './ng_control';
import {Control} from '../model';
import {Validators, NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators';
import {
setUpControl,
isPropertyUpdated,
@@ -22,6 +21,7 @@ import {
composeValidators,
composeAsyncValidators
} from './shared';
import {ValidatorFn, AsyncValidatorFn} from './validators';
const formControlBinding =
CONST_EXPR(new Provider(NgControl, {useExisting: forwardRef(() => NgModel)}));
@@ -88,9 +88,9 @@ export class NgModel extends NgControl implements OnChanges {
get path(): string[] { return []; }
get validator(): Function { return composeValidators(this._validators); }
get validator(): ValidatorFn { return composeValidators(this._validators); }
get asyncValidator(): Function { return composeAsyncValidators(this._asyncValidators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); }
viewToModelUpdate(newValue: any): void {
this.viewModel = newValue;
@@ -10,3 +10,11 @@ Function normalizeValidator(dynamic validator){
}
}
Function normalizeAsyncValidator(dynamic validator){
if (validator is Validator) {
return (c) => validator.validate(c);
} else {
return validator;
}
}
@@ -1,14 +1,18 @@
import {Validator} from './validators';
import {Control} from "../model";
import {AbstractControl} from "../model";
import {Validator, ValidatorFn, AsyncValidatorFn} from './validators';
export type ctrlFunc = ((c: Control) => {
[key: string]: any
});
export function normalizeValidator(validator: (ctrlFunc | Validator)): ctrlFunc {
export function normalizeValidator(validator: ValidatorFn | Validator): ValidatorFn {
if ((<Validator>validator).validate !== undefined) {
return (c: Control) => (<Validator>validator).validate(c);
return (c: AbstractControl) => (<Validator>validator).validate(c);
} else {
return <ctrlFunc>validator;
return <ValidatorFn>validator;
}
}
export function normalizeAsyncValidator(validator: AsyncValidatorFn | Validator): AsyncValidatorFn {
if ((<Validator>validator).validate !== undefined) {
return (c: AbstractControl) => Promise.resolve((<Validator>validator).validate(c));
} else {
return <AsyncValidatorFn>validator;
}
}
@@ -14,7 +14,8 @@ import {NumberValueAccessor} from './number_value_accessor';
import {CheckboxControlValueAccessor} from './checkbox_value_accessor';
import {SelectControlValueAccessor} from './select_control_value_accessor';
import {RadioControlValueAccessor} from './radio_control_value_accessor';
import {normalizeValidator} from './normalize_validator';
import {normalizeValidator, normalizeAsyncValidator} from './normalize_validator';
import {ValidatorFn, AsyncValidatorFn} from './validators';
export function controlPath(name: string, parent: ControlContainer): string[] {
@@ -56,13 +57,14 @@ function _throwError(dir: AbstractControlDirective, message: string): void {
throw new BaseException(`${message} '${path}'`);
}
export function composeValidators(validators: /* Array<Validator|Function> */ any[]): Function {
export function composeValidators(validators: /* Array<Validator|Function> */ any[]): ValidatorFn {
return isPresent(validators) ? Validators.compose(validators.map(normalizeValidator)) : null;
}
export function composeAsyncValidators(
validators: /* Array<Validator|Function> */ any[]): Function {
return isPresent(validators) ? Validators.composeAsync(validators.map(normalizeValidator)) : null;
validators: /* Array<Validator|Function> */ any[]): AsyncValidatorFn {
return isPresent(validators) ? Validators.composeAsync(validators.map(normalizeAsyncValidator)) :
null;
}
export function isPropertyUpdated(changes: {[key: string]: any}, viewModel: any): boolean {
@@ -1,11 +1,12 @@
import {forwardRef, Provider, OpaqueToken, Attribute, Directive} from 'angular2/core';
import {forwardRef, Provider, Attribute, Directive} from 'angular2/core';
import {CONST_EXPR} from 'angular2/src/facade/lang';
import {Validators, NG_VALIDATORS} from '../validators';
import {Control} from '../model';
import {AbstractControl} from '../model';
import * as modelModule from '../model';
import {NumberWrapper} from "angular2/src/facade/lang";
/**
* An interface that can be implemented by classes that can act as validators.
*
@@ -23,7 +24,7 @@ import {NumberWrapper} from "angular2/src/facade/lang";
* }
* ```
*/
export interface Validator { validate(c: modelModule.Control): {[key: string]: any}; }
export interface Validator { validate(c: modelModule.AbstractControl): {[key: string]: any}; }
const REQUIRED_VALIDATOR =
CONST_EXPR(new Provider(NG_VALIDATORS, {useValue: Validators.required, multi: true}));
@@ -45,6 +46,11 @@ const REQUIRED_VALIDATOR =
export class RequiredValidator {
}
export interface ValidatorFn { (c: AbstractControl): {[key: string]: any}; }
export interface AsyncValidatorFn {
(c: AbstractControl): any /*Promise<{[key: string]: any}>|Observable<{[key: string]: any}>*/;
}
/**
* Provivder which adds {@link MinLengthValidator} to {@link NG_VALIDATORS}.
*
@@ -64,13 +70,13 @@ const MIN_LENGTH_VALIDATOR = CONST_EXPR(
providers: [MIN_LENGTH_VALIDATOR]
})
export class MinLengthValidator implements Validator {
private _validator: Function;
private _validator: ValidatorFn;
constructor(@Attribute("minlength") minLength: string) {
this._validator = Validators.minLength(NumberWrapper.parseInt(minLength, 10));
}
validate(c: Control): {[key: string]: any} { return this._validator(c); }
validate(c: AbstractControl): {[key: string]: any} { return this._validator(c); }
}
/**
@@ -92,13 +98,13 @@ const MAX_LENGTH_VALIDATOR = CONST_EXPR(
providers: [MAX_LENGTH_VALIDATOR]
})
export class MaxLengthValidator implements Validator {
private _validator: Function;
private _validator: ValidatorFn;
constructor(@Attribute("maxlength") maxLength: string) {
this._validator = Validators.maxLength(NumberWrapper.parseInt(maxLength, 10));
}
validate(c: Control): {[key: string]: any} { return this._validator(c); }
validate(c: AbstractControl): {[key: string]: any} { return this._validator(c); }
}
@@ -121,11 +127,11 @@ const PATTERN_VALIDATOR = CONST_EXPR(
providers: [PATTERN_VALIDATOR]
})
export class PatternValidator implements Validator {
private _validator: Function;
private _validator: ValidatorFn;
constructor(@Attribute("pattern") pattern: string) {
this._validator = Validators.pattern(pattern);
}
validate(c: Control): {[key: string]: any} { return this._validator(c); }
validate(c: AbstractControl): {[key: string]: any} { return this._validator(c); }
}
@@ -2,6 +2,7 @@ import {Injectable} from 'angular2/core';
import {StringMapWrapper} from 'angular2/src/facade/collection';
import {isPresent, isArray, CONST_EXPR, Type} from 'angular2/src/facade/lang';
import * as modelModule from './model';
import {ValidatorFn, AsyncValidatorFn} from './directives/validators';
/**
@@ -56,16 +57,18 @@ export class FormBuilder {
group(controlsConfig: {[key: string]: any},
extra: {[key: string]: any} = null): modelModule.ControlGroup {
var controls = this._reduceControls(controlsConfig);
var optionals = isPresent(extra) ? StringMapWrapper.get(extra, "optionals") : null;
var validator = isPresent(extra) ? StringMapWrapper.get(extra, "validator") : null;
var asyncValidator = isPresent(extra) ? StringMapWrapper.get(extra, "asyncValidator") : null;
var optionals = <{[key: string]: boolean}>(
isPresent(extra) ? StringMapWrapper.get(extra, "optionals") : null);
var validator: ValidatorFn = isPresent(extra) ? StringMapWrapper.get(extra, "validator") : null;
var asyncValidator: AsyncValidatorFn =
isPresent(extra) ? StringMapWrapper.get(extra, "asyncValidator") : null;
return new modelModule.ControlGroup(controls, optionals, validator, asyncValidator);
}
/**
* Construct a new {@link Control} with the given `value`,`validator`, and `asyncValidator`.
*/
control(value: Object, validator: Function = null,
asyncValidator: Function = null): modelModule.Control {
control(value: Object, validator: ValidatorFn = null,
asyncValidator: AsyncValidatorFn = null): modelModule.Control {
return new modelModule.Control(value, validator, asyncValidator);
}
@@ -73,8 +76,8 @@ export class FormBuilder {
* Construct an array of {@link Control}s from the given `controlsConfig` array of
* configuration, with the given optional `validator` and `asyncValidator`.
*/
array(controlsConfig: any[], validator: Function = null,
asyncValidator: Function = null): modelModule.ControlArray {
array(controlsConfig: any[], validator: ValidatorFn = null,
asyncValidator: AsyncValidatorFn = null): modelModule.ControlArray {
var controls = controlsConfig.map(c => this._createControl(c));
return new modelModule.ControlArray(controls, validator, asyncValidator);
}
@@ -98,12 +101,12 @@ export class FormBuilder {
} else if (isArray(controlConfig)) {
var value = controlConfig[0];
var validator = controlConfig.length > 1 ? controlConfig[1] : null;
var asyncValidator = controlConfig.length > 2 ? controlConfig[2] : null;
var validator: ValidatorFn = controlConfig.length > 1 ? controlConfig[1] : null;
var asyncValidator: AsyncValidatorFn = controlConfig.length > 2 ? controlConfig[2] : null;
return this.control(value, validator, asyncValidator);
} else {
return this.control(controlConfig);
}
}
}
}
+14 -10
View File
@@ -1,7 +1,8 @@
import {StringWrapper, isPresent, isBlank, normalizeBool} from 'angular2/src/facade/lang';
import {isPresent, isBlank, normalizeBool} from 'angular2/src/facade/lang';
import {Observable, EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
import {PromiseWrapper} from 'angular2/src/facade/promise';
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {ValidatorFn, AsyncValidatorFn} from './directives/validators';
/**
* Indicates that a Control is valid, i.e. that no errors exist in the input value.
@@ -64,7 +65,7 @@ export abstract class AbstractControl {
private _parent: ControlGroup | ControlArray;
private _asyncValidationSubscription: any;
constructor(public validator: Function, public asyncValidator: Function) {}
constructor(public validator: ValidatorFn, public asyncValidator: AsyncValidatorFn) {}
get value(): any { return this._value; }
@@ -137,15 +138,17 @@ export abstract class AbstractControl {
}
}
private _runValidator() { return isPresent(this.validator) ? this.validator(this) : null; }
private _runValidator(): {[key: string]: any} {
return isPresent(this.validator) ? this.validator(this) : null;
}
private _runAsyncValidator(emitEvent: boolean): void {
if (isPresent(this.asyncValidator)) {
this._status = PENDING;
this._cancelExistingSubscription();
var obs = toObservable(this.asyncValidator(this));
this._asyncValidationSubscription =
ObservableWrapper.subscribe(obs, res => this.setErrors(res, {emitEvent: emitEvent}));
this._asyncValidationSubscription = ObservableWrapper.subscribe(
obs, (res: {[key: string]: any}) => this.setErrors(res, {emitEvent: emitEvent}));
}
}
@@ -268,7 +271,8 @@ export class Control extends AbstractControl {
/** @internal */
_onChange: Function;
constructor(value: any = null, validator: Function = null, asyncValidator: Function = null) {
constructor(value: any = null, validator: ValidatorFn = null,
asyncValidator: AsyncValidatorFn = null) {
super(validator, asyncValidator);
this._value = value;
this.updateValueAndValidity({onlySelf: true, emitEvent: false});
@@ -331,8 +335,8 @@ export class ControlGroup extends AbstractControl {
private _optionals: {[key: string]: boolean};
constructor(public controls: {[key: string]: AbstractControl},
optionals: {[key: string]: boolean} = null, validator: Function = null,
asyncValidator: Function = null) {
optionals: {[key: string]: boolean} = null, validator: ValidatorFn = null,
asyncValidator: AsyncValidatorFn = null) {
super(validator, asyncValidator);
this._optionals = isPresent(optionals) ? optionals : {};
this._initObservables();
@@ -444,8 +448,8 @@ export class ControlGroup extends AbstractControl {
* ### Example ([live demo](http://plnkr.co/edit/23DESOpbNnBpBHZt1BR4?p=preview))
*/
export class ControlArray extends AbstractControl {
constructor(public controls: AbstractControl[], validator: Function = null,
asyncValidator: Function = null) {
constructor(public controls: AbstractControl[], validator: ValidatorFn = null,
asyncValidator: AsyncValidatorFn = null) {
super(validator, asyncValidator);
this._initObservables();
this._setParentForControls();
+23 -15
View File
@@ -5,6 +5,7 @@ import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {OpaqueToken} from 'angular2/core';
import * as modelModule from './model';
import {ValidatorFn, AsyncValidatorFn} from './directives/validators';
/**
* Providers for validators to be used for {@link Control}s in a form.
@@ -43,7 +44,7 @@ export class Validators {
/**
* Validator that requires controls to have a non-empty value.
*/
static required(control: modelModule.Control): {[key: string]: boolean} {
static required(control: modelModule.AbstractControl): {[key: string]: boolean} {
return isBlank(control.value) || (isString(control.value) && control.value == "") ?
{"required": true} :
null;
@@ -52,8 +53,8 @@ export class Validators {
/**
* Validator that requires controls to have a value of a minimum length.
*/
static minLength(minLength: number): Function {
return (control: modelModule.Control): {[key: string]: any} => {
static minLength(minLength: number): ValidatorFn {
return (control: modelModule.AbstractControl): {[key: string]: any} => {
if (isPresent(Validators.required(control))) return null;
var v: string = control.value;
return v.length < minLength ?
@@ -65,8 +66,8 @@ export class Validators {
/**
* Validator that requires controls to have a value of a maximum length.
*/
static maxLength(maxLength: number): Function {
return (control: modelModule.Control): {[key: string]: any} => {
static maxLength(maxLength: number): ValidatorFn {
return (control: modelModule.AbstractControl): {[key: string]: any} => {
if (isPresent(Validators.required(control))) return null;
var v: string = control.value;
return v.length > maxLength ?
@@ -78,8 +79,8 @@ export class Validators {
/**
* Validator that requires a control to match a regex to its value.
*/
static pattern(pattern: string): Function {
return (control: modelModule.Control): {[key: string]: any} => {
static pattern(pattern: string): ValidatorFn {
return (control: modelModule.AbstractControl): {[key: string]: any} => {
if (isPresent(Validators.required(control))) return null;
let regex = new RegExp(`^${pattern}$`);
let v: string = control.value;
@@ -91,13 +92,13 @@ export class Validators {
/**
* No-op validator.
*/
static nullValidator(c: any): {[key: string]: boolean} { return null; }
static nullValidator(c: modelModule.AbstractControl): {[key: string]: boolean} { return null; }
/**
* Compose multiple validators into a single function that returns the union
* of the individual error maps.
*/
static compose(validators: Function[]): Function {
static compose(validators: ValidatorFn[]): ValidatorFn {
if (isBlank(validators)) return null;
var presentValidators = validators.filter(isPresent);
if (presentValidators.length == 0) return null;
@@ -107,13 +108,13 @@ export class Validators {
};
}
static composeAsync(validators: Function[]): Function {
static composeAsync(validators: AsyncValidatorFn[]): AsyncValidatorFn {
if (isBlank(validators)) return null;
var presentValidators = validators.filter(isPresent);
if (presentValidators.length == 0) return null;
return function(control: modelModule.AbstractControl) {
let promises = _executeValidators(control, presentValidators).map(_convertToPromise);
let promises = _executeAsyncValidators(control, presentValidators).map(_convertToPromise);
return PromiseWrapper.all(promises).then(_mergeErrors);
};
}
@@ -123,13 +124,20 @@ function _convertToPromise(obj: any): any {
return PromiseWrapper.isPromise(obj) ? obj : ObservableWrapper.toPromise(obj);
}
function _executeValidators(control: modelModule.AbstractControl, validators: Function[]): any[] {
function _executeValidators(control: modelModule.AbstractControl,
validators: ValidatorFn[]): any[] {
return validators.map(v => v(control));
}
function _executeAsyncValidators(control: modelModule.AbstractControl,
validators: AsyncValidatorFn[]): any[] {
return validators.map(v => v(control));
}
function _mergeErrors(arrayOfErrors: any[]): {[key: string]: any} {
var res = arrayOfErrors.reduce((res, errors) => {
return isPresent(errors) ? StringMapWrapper.merge(<any>res, <any>errors) : res;
}, {});
var res: {[key: string]: any} =
arrayOfErrors.reduce((res: {[key: string]: any}, errors: {[key: string]: any}) => {
return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res;
}, {});
return StringMapWrapper.isEmpty(res) ? null : res;
}