fix(forms): Update types for TypeScript nullability support

This reverts commit 6d930d2fc5.
This commit is contained in:
Miško Hevery 2017-04-17 11:13:30 -07:00 committed by Tobias Bosch
parent bc431888f3
commit 57bc245cb4
27 changed files with 343 additions and 330 deletions

View File

@ -18,45 +18,49 @@ import {ValidationErrors} from './validators';
* @stable * @stable
*/ */
export abstract class AbstractControlDirective { export abstract class AbstractControlDirective {
get control(): AbstractControl { throw new Error('unimplemented'); } abstract get control(): AbstractControl|null;
get value(): any { return this.control ? this.control.value : null; } get value(): any { return this.control ? this.control.value : null; }
get valid(): boolean { return this.control ? this.control.valid : null; } get valid(): boolean|null { return this.control ? this.control.valid : null; }
get invalid(): boolean { return this.control ? this.control.invalid : null; } get invalid(): boolean|null { return this.control ? this.control.invalid : null; }
get pending(): boolean { return this.control ? this.control.pending : null; } get pending(): boolean|null { return this.control ? this.control.pending : null; }
get errors(): ValidationErrors|null { return this.control ? this.control.errors : null; } get errors(): ValidationErrors|null { return this.control ? this.control.errors : null; }
get pristine(): boolean { return this.control ? this.control.pristine : null; } get pristine(): boolean|null { return this.control ? this.control.pristine : null; }
get dirty(): boolean { return this.control ? this.control.dirty : null; } get dirty(): boolean|null { return this.control ? this.control.dirty : null; }
get touched(): boolean { return this.control ? this.control.touched : null; } get touched(): boolean|null { return this.control ? this.control.touched : null; }
get untouched(): boolean { return this.control ? this.control.untouched : null; } get untouched(): boolean|null { return this.control ? this.control.untouched : null; }
get disabled(): boolean { return this.control ? this.control.disabled : null; } get disabled(): boolean|null { return this.control ? this.control.disabled : null; }
get enabled(): boolean { return this.control ? this.control.enabled : null; } get enabled(): boolean|null { return this.control ? this.control.enabled : null; }
get statusChanges(): Observable<any> { return this.control ? this.control.statusChanges : null; } get statusChanges(): Observable<any>|null {
return this.control ? this.control.statusChanges : null;
}
get valueChanges(): Observable<any> { return this.control ? this.control.valueChanges : null; } get valueChanges(): Observable<any>|null {
return this.control ? this.control.valueChanges : null;
}
get path(): string[] { return null; } get path(): string[]|null { return null; }
reset(value: any = undefined): void { reset(value: any = undefined): void {
if (this.control) this.control.reset(value); if (this.control) this.control.reset(value);
} }
hasError(errorCode: string, path: string[] = null): boolean { hasError(errorCode: string, path?: string[]): boolean {
return this.control ? this.control.hasError(errorCode, path) : false; return this.control ? this.control.hasError(errorCode, path) : false;
} }
getError(errorCode: string, path: string[] = null): any { getError(errorCode: string, path?: string[]): any {
return this.control ? this.control.getError(errorCode, path) : null; return this.control ? this.control.getError(errorCode, path) : null;
} }
} }

View File

@ -34,7 +34,7 @@ export class AbstractFormGroupDirective extends ControlContainer implements OnIn
ngOnInit(): void { ngOnInit(): void {
this._checkParentType(); this._checkParentType();
this.formDirective.addFormGroup(this); this.formDirective !.addFormGroup(this);
} }
ngOnDestroy(): void { ngOnDestroy(): void {
@ -46,7 +46,7 @@ export class AbstractFormGroupDirective extends ControlContainer implements OnIn
/** /**
* Get the {@link FormGroup} backing this binding. * Get the {@link FormGroup} backing this binding.
*/ */
get control(): FormGroup { return this.formDirective.getFormGroup(this); } get control(): FormGroup { return this.formDirective !.getFormGroup(this); }
/** /**
* Get the path to this control group. * Get the path to this control group.
@ -56,11 +56,13 @@ export class AbstractFormGroupDirective extends ControlContainer implements OnIn
/** /**
* Get the {@link Form} to which this group belongs. * Get the {@link Form} to which this group belongs.
*/ */
get formDirective(): Form { return this._parent ? this._parent.formDirective : null; } get formDirective(): Form|null { return this._parent ? this._parent.formDirective : null; }
get validator(): ValidatorFn { return composeValidators(this._validators); } get validator(): ValidatorFn|null { return composeValidators(this._validators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); } get asyncValidator(): AsyncValidatorFn|null {
return composeAsyncValidators(this._asyncValidators);
}
/** @internal */ /** @internal */
_checkParentType(): void {} _checkParentType(): void {}

View File

@ -17,16 +17,16 @@ import {Form} from './form_interface';
* *
* @stable * @stable
*/ */
export class ControlContainer extends AbstractControlDirective { export abstract class ControlContainer extends AbstractControlDirective {
name: string; name: string;
/** /**
* Get the form to which this container belongs. * Get the form to which this container belongs.
*/ */
get formDirective(): Form { return null; } get formDirective(): Form|null { return null; }
/** /**
* Get the path to this container. * Get the path to this container.
*/ */
get path(): string[] { return null; } get path(): string[]|null { return null; }
} }

View File

@ -26,16 +26,16 @@ function unimplemented(): any {
*/ */
export abstract class NgControl extends AbstractControlDirective { export abstract class NgControl extends AbstractControlDirective {
/** @internal */ /** @internal */
_parent: ControlContainer = null; _parent: ControlContainer|null = null;
name: string = null; name: string|null = null;
valueAccessor: ControlValueAccessor = null; valueAccessor: ControlValueAccessor|null = null;
/** @internal */ /** @internal */
_rawValidators: Array<Validator|ValidatorFn> = []; _rawValidators: Array<Validator|ValidatorFn> = [];
/** @internal */ /** @internal */
_rawAsyncValidators: Array<AsyncValidator|AsyncValidatorFn> = []; _rawAsyncValidators: Array<AsyncValidator|AsyncValidatorFn> = [];
get validator(): ValidatorFn { return <ValidatorFn>unimplemented(); } get validator(): ValidatorFn|null { return <ValidatorFn>unimplemented(); }
get asyncValidator(): AsyncValidatorFn { return <AsyncValidatorFn>unimplemented(); } get asyncValidator(): AsyncValidatorFn|null { return <AsyncValidatorFn>unimplemented(); }
abstract viewToModelUpdate(newValue: any): void; abstract viewToModelUpdate(newValue: any): void;
} }

View File

@ -130,7 +130,7 @@ export class NgForm extends ControlContainer implements Form {
updateModel(dir: NgControl, value: any): void { updateModel(dir: NgControl, value: any): void {
resolvedPromise.then(() => { resolvedPromise.then(() => {
const ctrl = <FormControl>this.form.get(dir.path); const ctrl = <FormControl>this.form.get(dir.path !);
ctrl.setValue(value); ctrl.setValue(value);
}); });
} }

View File

@ -158,9 +158,9 @@ export class NgModel extends NgControl implements OnChanges,
get formDirective(): any { return this._parent ? this._parent.formDirective : null; } get formDirective(): any { return this._parent ? this._parent.formDirective : null; }
get validator(): ValidatorFn { return composeValidators(this._rawValidators); } get validator(): ValidatorFn|null { return composeValidators(this._rawValidators); }
get asyncValidator(): AsyncValidatorFn { get asyncValidator(): AsyncValidatorFn|null {
return composeAsyncValidators(this._rawAsyncValidators); return composeAsyncValidators(this._rawAsyncValidators);
} }
@ -176,7 +176,7 @@ export class NgModel extends NgControl implements OnChanges,
} }
private _isStandalone(): boolean { private _isStandalone(): boolean {
return !this._parent || (this.options && this.options.standalone); return !this._parent || !!(this.options && this.options.standalone);
} }
private _setUpStandalone(): void { private _setUpStandalone(): void {

View File

@ -47,7 +47,7 @@ export class NumberValueAccessor implements ControlValueAccessor {
this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', normalizedValue); this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', normalizedValue);
} }
registerOnChange(fn: (_: number) => void): void { registerOnChange(fn: (_: number|null) => void): void {
this.onChange = (value) => { fn(value == '' ? null : parseFloat(value)); }; this.onChange = (value) => { fn(value == '' ? null : parseFloat(value)); };
} }
registerOnTouched(fn: () => void): void { this.onTouched = fn; } registerOnTouched(fn: () => void): void { this.onTouched = fn; }

View File

@ -45,7 +45,7 @@ export class RangeValueAccessor implements ControlValueAccessor {
this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', parseFloat(value)); this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', parseFloat(value));
} }
registerOnChange(fn: (_: number) => void): void { registerOnChange(fn: (_: number|null) => void): void {
this.onChange = (value) => { fn(value == '' ? null : parseFloat(value)); }; this.onChange = (value) => { fn(value == '' ? null : parseFloat(value)); };
} }

View File

@ -88,8 +88,8 @@ export class FormControlDirective extends NgControl implements OnChanges {
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
if (this._isControlChanged(changes)) { if (this._isControlChanged(changes)) {
setUpControl(this.form, this); setUpControl(this.form, this);
if (this.control.disabled && this.valueAccessor.setDisabledState) { if (this.control.disabled && this.valueAccessor !.setDisabledState) {
this.valueAccessor.setDisabledState(true); this.valueAccessor !.setDisabledState !(true);
} }
this.form.updateValueAndValidity({emitEvent: false}); this.form.updateValueAndValidity({emitEvent: false});
} }
@ -101,9 +101,9 @@ export class FormControlDirective extends NgControl implements OnChanges {
get path(): string[] { return []; } get path(): string[] { return []; }
get validator(): ValidatorFn { return composeValidators(this._rawValidators); } get validator(): ValidatorFn|null { return composeValidators(this._rawValidators); }
get asyncValidator(): AsyncValidatorFn { get asyncValidator(): AsyncValidatorFn|null {
return composeAsyncValidators(this._rawAsyncValidators); return composeAsyncValidators(this._rawAsyncValidators);
} }

View File

@ -125,14 +125,14 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
this.update.emit(newValue); this.update.emit(newValue);
} }
get path(): string[] { return controlPath(this.name, this._parent); } get path(): string[] { return controlPath(this.name, this._parent !); }
get formDirective(): any { return this._parent ? this._parent.formDirective : null; } get formDirective(): any { return this._parent ? this._parent.formDirective : null; }
get validator(): ValidatorFn { return composeValidators(this._rawValidators); } get validator(): ValidatorFn|null { return composeValidators(this._rawValidators); }
get asyncValidator(): AsyncValidatorFn { get asyncValidator(): AsyncValidatorFn {
return composeAsyncValidators(this._rawAsyncValidators); return composeAsyncValidators(this._rawAsyncValidators) !;
} }
get control(): FormControl { return this._control; } get control(): FormControl { return this._control; }
@ -151,8 +151,8 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
private _setUpControl() { private _setUpControl() {
this._checkParentType(); this._checkParentType();
this._control = this.formDirective.addControl(this); this._control = this.formDirective.addControl(this);
if (this.control.disabled && this.valueAccessor.setDisabledState) { if (this.control.disabled && this.valueAccessor !.setDisabledState) {
this.valueAccessor.setDisabledState(true); this.valueAccessor !.setDisabledState !(true);
} }
this._added = true; this._added = true;
} }

View File

@ -69,7 +69,7 @@ export class FormGroupDirective extends ControlContainer implements Form,
private _oldForm: FormGroup; private _oldForm: FormGroup;
directives: FormControlName[] = []; directives: FormControlName[] = [];
@Input('formGroup') form: FormGroup = null; @Input('formGroup') form: FormGroup = null !;
@Output() ngSubmit = new EventEmitter(); @Output() ngSubmit = new EventEmitter();
constructor( constructor(
@ -167,10 +167,10 @@ export class FormGroupDirective extends ControlContainer implements Form,
private _updateValidators() { private _updateValidators() {
const sync = composeValidators(this._validators); const sync = composeValidators(this._validators);
this.form.validator = Validators.compose([this.form.validator, sync]); this.form.validator = Validators.compose([this.form.validator !, sync !]);
const async = composeAsyncValidators(this._asyncValidators); const async = composeAsyncValidators(this._asyncValidators);
this.form.asyncValidator = Validators.composeAsync([this.form.asyncValidator, async]); this.form.asyncValidator = Validators.composeAsync([this.form.asyncValidator !, async !]);
} }
private _checkFormPresent() { private _checkFormPresent() {

View File

@ -166,7 +166,7 @@ export class FormArrayName extends ControlContainer implements OnInit, OnDestroy
ngOnInit(): void { ngOnInit(): void {
this._checkParentType(); this._checkParentType();
this.formDirective.addFormArray(this); this.formDirective !.addFormArray(this);
} }
ngOnDestroy(): void { ngOnDestroy(): void {
@ -175,17 +175,19 @@ export class FormArrayName extends ControlContainer implements OnInit, OnDestroy
} }
} }
get control(): FormArray { return this.formDirective.getFormArray(this); } get control(): FormArray { return this.formDirective !.getFormArray(this); }
get formDirective(): FormGroupDirective { get formDirective(): FormGroupDirective|null {
return this._parent ? <FormGroupDirective>this._parent.formDirective : null; return this._parent ? <FormGroupDirective>this._parent.formDirective : null;
} }
get path(): string[] { return controlPath(this.name, this._parent); } get path(): string[] { return controlPath(this.name, this._parent); }
get validator(): ValidatorFn { return composeValidators(this._validators); } get validator(): ValidatorFn|null { return composeValidators(this._validators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); } get asyncValidator(): AsyncValidatorFn|null {
return composeAsyncValidators(this._asyncValidators);
}
private _checkParentType(): void { private _checkParentType(): void {
if (_hasInvalidParent(this._parent)) { if (_hasInvalidParent(this._parent)) {

View File

@ -15,7 +15,7 @@ export const SELECT_VALUE_ACCESSOR: Provider = {
multi: true multi: true
}; };
function _buildValueString(id: string, value: any): string { function _buildValueString(id: string | null, value: any): string {
if (id == null) return `${value}`; if (id == null) return `${value}`;
if (value && typeof value === 'object') value = 'Object'; if (value && typeof value === 'object') value = 'Object';
return `${id}: ${value}`.slice(0, 50); return `${id}: ${value}`.slice(0, 50);
@ -118,7 +118,7 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
writeValue(value: any): void { writeValue(value: any): void {
this.value = value; this.value = value;
const id: string = this._getOptionId(value); const id: string|null = this._getOptionId(value);
if (id == null) { if (id == null) {
this._renderer.setElementProperty(this._elementRef.nativeElement, 'selectedIndex', -1); this._renderer.setElementProperty(this._elementRef.nativeElement, 'selectedIndex', -1);
} }
@ -142,7 +142,7 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
_registerOption(): string { return (this._idCounter++).toString(); } _registerOption(): string { return (this._idCounter++).toString(); }
/** @internal */ /** @internal */
_getOptionId(value: any): string { _getOptionId(value: any): string|null {
for (const id of Array.from(this._optionMap.keys())) { for (const id of Array.from(this._optionMap.keys())) {
if (this._compareWith(this._optionMap.get(id), value)) return id; if (this._compareWith(this._optionMap.get(id), value)) return id;
} }

View File

@ -149,9 +149,9 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
} }
/** @internal */ /** @internal */
_getOptionId(value: any): string { _getOptionId(value: any): string|null {
for (const id of Array.from(this._optionMap.keys())) { for (const id of Array.from(this._optionMap.keys())) {
if (this._compareWith(this._optionMap.get(id)._value, value)) return id; if (this._compareWith(this._optionMap.get(id) !._value, value)) return id;
} }
return null; return null;
} }
@ -159,7 +159,7 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
/** @internal */ /** @internal */
_getOptionValue(valueString: string): any { _getOptionValue(valueString: string): any {
const id: string = _extractId(valueString); const id: string = _extractId(valueString);
return this._optionMap.has(id) ? this._optionMap.get(id)._value : valueString; return this._optionMap.has(id) ? this._optionMap.get(id) !._value : valueString;
} }
} }

View File

@ -27,55 +27,55 @@ import {AsyncValidator, AsyncValidatorFn, Validator, ValidatorFn} from './valida
export function controlPath(name: string, parent: ControlContainer): string[] { export function controlPath(name: string, parent: ControlContainer): string[] {
return [...parent.path, name]; return [...parent.path !, name];
} }
export function setUpControl(control: FormControl, dir: NgControl): void { export function setUpControl(control: FormControl, dir: NgControl): void {
if (!control) _throwError(dir, 'Cannot find control with'); if (!control) _throwError(dir, 'Cannot find control with');
if (!dir.valueAccessor) _throwError(dir, 'No value accessor for form control with'); if (!dir.valueAccessor) _throwError(dir, 'No value accessor for form control with');
control.validator = Validators.compose([control.validator, dir.validator]); control.validator = Validators.compose([control.validator !, dir.validator]);
control.asyncValidator = Validators.composeAsync([control.asyncValidator, dir.asyncValidator]); control.asyncValidator = Validators.composeAsync([control.asyncValidator !, dir.asyncValidator]);
dir.valueAccessor.writeValue(control.value); dir.valueAccessor !.writeValue(control.value);
// view -> model // view -> model
dir.valueAccessor.registerOnChange((newValue: any) => { dir.valueAccessor !.registerOnChange((newValue: any) => {
dir.viewToModelUpdate(newValue); dir.viewToModelUpdate(newValue);
control.markAsDirty(); control.markAsDirty();
control.setValue(newValue, {emitModelToViewChange: false}); control.setValue(newValue, {emitModelToViewChange: false});
}); });
// touched // touched
dir.valueAccessor.registerOnTouched(() => control.markAsTouched()); dir.valueAccessor !.registerOnTouched(() => control.markAsTouched());
control.registerOnChange((newValue: any, emitModelEvent: boolean) => { control.registerOnChange((newValue: any, emitModelEvent: boolean) => {
// control -> view // control -> view
dir.valueAccessor.writeValue(newValue); dir.valueAccessor !.writeValue(newValue);
// control -> ngModel // control -> ngModel
if (emitModelEvent) dir.viewToModelUpdate(newValue); if (emitModelEvent) dir.viewToModelUpdate(newValue);
}); });
if (dir.valueAccessor.setDisabledState) { if (dir.valueAccessor !.setDisabledState) {
control.registerOnDisabledChange( control.registerOnDisabledChange(
(isDisabled: boolean) => { dir.valueAccessor.setDisabledState(isDisabled); }); (isDisabled: boolean) => { dir.valueAccessor !.setDisabledState !(isDisabled); });
} }
// re-run validation when validator binding changes, e.g. minlength=3 -> minlength=4 // re-run validation when validator binding changes, e.g. minlength=3 -> minlength=4
dir._rawValidators.forEach((validator: Validator | ValidatorFn) => { dir._rawValidators.forEach((validator: Validator | ValidatorFn) => {
if ((<Validator>validator).registerOnValidatorChange) if ((<Validator>validator).registerOnValidatorChange)
(<Validator>validator).registerOnValidatorChange(() => control.updateValueAndValidity()); (<Validator>validator).registerOnValidatorChange !(() => control.updateValueAndValidity());
}); });
dir._rawAsyncValidators.forEach((validator: AsyncValidator | AsyncValidatorFn) => { dir._rawAsyncValidators.forEach((validator: AsyncValidator | AsyncValidatorFn) => {
if ((<Validator>validator).registerOnValidatorChange) if ((<Validator>validator).registerOnValidatorChange)
(<Validator>validator).registerOnValidatorChange(() => control.updateValueAndValidity()); (<Validator>validator).registerOnValidatorChange !(() => control.updateValueAndValidity());
}); });
} }
export function cleanUpControl(control: FormControl, dir: NgControl) { export function cleanUpControl(control: FormControl, dir: NgControl) {
dir.valueAccessor.registerOnChange(() => _noControlError(dir)); dir.valueAccessor !.registerOnChange(() => _noControlError(dir));
dir.valueAccessor.registerOnTouched(() => _noControlError(dir)); dir.valueAccessor !.registerOnTouched(() => _noControlError(dir));
dir._rawValidators.forEach((validator: any) => { dir._rawValidators.forEach((validator: any) => {
if (validator.registerOnValidatorChange) { if (validator.registerOnValidatorChange) {
@ -105,9 +105,9 @@ function _noControlError(dir: NgControl) {
function _throwError(dir: AbstractControlDirective, message: string): void { function _throwError(dir: AbstractControlDirective, message: string): void {
let messageEnd: string; let messageEnd: string;
if (dir.path.length > 1) { if (dir.path !.length > 1) {
messageEnd = `path: '${dir.path.join(' -> ')}'`; messageEnd = `path: '${dir.path!.join(' -> ')}'`;
} else if (dir.path[0]) { } else if (dir.path ![0]) {
messageEnd = `name: '${dir.path}'`; messageEnd = `name: '${dir.path}'`;
} else { } else {
messageEnd = 'unspecified name attribute'; messageEnd = 'unspecified name attribute';
@ -115,11 +115,12 @@ function _throwError(dir: AbstractControlDirective, message: string): void {
throw new Error(`${message} ${messageEnd}`); throw new Error(`${message} ${messageEnd}`);
} }
export function composeValidators(validators: Array<Validator|Function>): ValidatorFn { export function composeValidators(validators: Array<Validator|Function>): ValidatorFn|null {
return validators != null ? Validators.compose(validators.map(normalizeValidator)) : null; return validators != null ? Validators.compose(validators.map(normalizeValidator)) : null;
} }
export function composeAsyncValidators(validators: Array<Validator|Function>): AsyncValidatorFn { export function composeAsyncValidators(validators: Array<Validator|Function>): AsyncValidatorFn|
null {
return validators != null ? Validators.composeAsync(validators.map(normalizeAsyncValidator)) : return validators != null ? Validators.composeAsync(validators.map(normalizeAsyncValidator)) :
null; null;
} }
@ -147,12 +148,12 @@ export function isBuiltInAccessor(valueAccessor: ControlValueAccessor): boolean
// TODO: vsavkin remove it once https://github.com/angular/angular/issues/3011 is implemented // TODO: vsavkin remove it once https://github.com/angular/angular/issues/3011 is implemented
export function selectValueAccessor( export function selectValueAccessor(
dir: NgControl, valueAccessors: ControlValueAccessor[]): ControlValueAccessor { dir: NgControl, valueAccessors: ControlValueAccessor[]): ControlValueAccessor|null {
if (!valueAccessors) return null; if (!valueAccessors) return null;
let defaultAccessor: ControlValueAccessor; let defaultAccessor: ControlValueAccessor|undefined = undefined;
let builtinAccessor: ControlValueAccessor; let builtinAccessor: ControlValueAccessor|undefined = undefined;
let customAccessor: ControlValueAccessor; let customAccessor: ControlValueAccessor|undefined = undefined;
valueAccessors.forEach((v: ControlValueAccessor) => { valueAccessors.forEach((v: ControlValueAccessor) => {
if (v.constructor === DefaultValueAccessor) { if (v.constructor === DefaultValueAccessor) {
defaultAccessor = v; defaultAccessor = v;

View File

@ -39,7 +39,7 @@ export class FormBuilder {
* *
* See the {@link FormGroup} constructor for more details. * See the {@link FormGroup} constructor for more details.
*/ */
group(controlsConfig: {[key: string]: any}, extra: {[key: string]: any} = null): FormGroup { group(controlsConfig: {[key: string]: any}, extra: {[key: string]: any}|null = null): FormGroup {
const controls = this._reduceControls(controlsConfig); const controls = this._reduceControls(controlsConfig);
const validator: ValidatorFn = extra != null ? extra['validator'] : null; const validator: ValidatorFn = extra != null ? extra['validator'] : null;
const asyncValidator: AsyncValidatorFn = extra != null ? extra['asyncValidator'] : null; const asyncValidator: AsyncValidatorFn = extra != null ? extra['asyncValidator'] : null;
@ -54,8 +54,8 @@ export class FormBuilder {
* *
*/ */
control( control(
formState: Object, validator: ValidatorFn|ValidatorFn[] = null, formState: Object, validator?: ValidatorFn|ValidatorFn[]|null,
asyncValidator: AsyncValidatorFn|AsyncValidatorFn[] = null): FormControl { asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null): FormControl {
return new FormControl(formState, validator, asyncValidator); return new FormControl(formState, validator, asyncValidator);
} }
@ -64,8 +64,8 @@ export class FormBuilder {
* configuration, with the given optional `validator` and `asyncValidator`. * configuration, with the given optional `validator` and `asyncValidator`.
*/ */
array( array(
controlsConfig: any[], validator: ValidatorFn = null, controlsConfig: any[], validator?: ValidatorFn|null,
asyncValidator: AsyncValidatorFn = null): FormArray { asyncValidator?: AsyncValidatorFn|null): FormArray {
const controls = controlsConfig.map(c => this._createControl(c)); const controls = controlsConfig.map(c => this._createControl(c));
return new FormArray(controls, validator, asyncValidator); return new FormArray(controls, validator, asyncValidator);
} }

View File

@ -42,7 +42,7 @@ function _find(control: AbstractControl, path: Array<string|number>| string, del
} }
if (path instanceof Array && (path.length === 0)) return null; if (path instanceof Array && (path.length === 0)) return null;
return (<Array<string|number>>path).reduce((v, name) => { return (<Array<string|number>>path).reduce((v: AbstractControl, name) => {
if (v instanceof FormGroup) { if (v instanceof FormGroup) {
return v.controls[name] || null; return v.controls[name] || null;
} }
@ -55,13 +55,14 @@ function _find(control: AbstractControl, path: Array<string|number>| string, del
}, control); }, control);
} }
function coerceToValidator(validator: ValidatorFn | ValidatorFn[]): ValidatorFn { function coerceToValidator(validator?: ValidatorFn | ValidatorFn[] | null): ValidatorFn|null {
return Array.isArray(validator) ? composeValidators(validator) : validator; return Array.isArray(validator) ? composeValidators(validator) : validator || null;
} }
function coerceToAsyncValidator(asyncValidator: AsyncValidatorFn | AsyncValidatorFn[]): function coerceToAsyncValidator(asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null):
AsyncValidatorFn { AsyncValidatorFn|null {
return Array.isArray(asyncValidator) ? composeAsyncValidators(asyncValidator) : asyncValidator; return Array.isArray(asyncValidator) ? composeAsyncValidators(asyncValidator) :
asyncValidator || null;
} }
/** /**
@ -90,7 +91,7 @@ export abstract class AbstractControl {
private _parent: FormGroup|FormArray; private _parent: FormGroup|FormArray;
private _asyncValidationSubscription: any; private _asyncValidationSubscription: any;
constructor(public validator: ValidatorFn, public asyncValidator: AsyncValidatorFn) {} constructor(public validator: ValidatorFn|null, public asyncValidator: AsyncValidatorFn|null) {}
/** /**
* The value of the control. * The value of the control.
@ -209,7 +210,7 @@ export abstract class AbstractControl {
* Sets the synchronous validators that are active on this control. Calling * Sets the synchronous validators that are active on this control. Calling
* this will overwrite any existing sync validators. * this will overwrite any existing sync validators.
*/ */
setValidators(newValidator: ValidatorFn|ValidatorFn[]): void { setValidators(newValidator: ValidatorFn|ValidatorFn[]|null): void {
this.validator = coerceToValidator(newValidator); this.validator = coerceToValidator(newValidator);
} }
@ -322,7 +323,7 @@ export abstract class AbstractControl {
this._statusChanges.emit(this._status); this._statusChanges.emit(this._status);
} }
this._updateAncestors(onlySelf); this._updateAncestors(!!onlySelf);
this._onDisabledChange.forEach((changeFn) => changeFn(true)); this._onDisabledChange.forEach((changeFn) => changeFn(true));
} }
@ -338,7 +339,7 @@ export abstract class AbstractControl {
this._forEachChild((control: AbstractControl) => { control.enable({onlySelf: true}); }); this._forEachChild((control: AbstractControl) => { control.enable({onlySelf: true}); });
this.updateValueAndValidity({onlySelf: true, emitEvent}); this.updateValueAndValidity({onlySelf: true, emitEvent});
this._updateAncestors(onlySelf); this._updateAncestors(!!onlySelf);
this._onDisabledChange.forEach((changeFn) => changeFn(false)); this._onDisabledChange.forEach((changeFn) => changeFn(false));
} }
@ -409,7 +410,7 @@ export abstract class AbstractControl {
return this.validator ? this.validator(this) : null; return this.validator ? this.validator(this) : null;
} }
private _runAsyncValidator(emitEvent: boolean): void { private _runAsyncValidator(emitEvent?: boolean): void {
if (this.asyncValidator) { if (this.asyncValidator) {
this._status = PENDING; this._status = PENDING;
const obs = toObservable(this.asyncValidator(this)); const obs = toObservable(this.asyncValidator(this));
@ -465,7 +466,7 @@ export abstract class AbstractControl {
* *
* * `this.form.get(['person', 'name']);` * * `this.form.get(['person', 'name']);`
*/ */
get(path: Array<string|number>|string): AbstractControl { return _find(this, path, '.'); } get(path: Array<string|number>|string): AbstractControl|null { return _find(this, path, '.'); }
/** /**
* Returns true if the control with the given path has the error specified. Otherwise * Returns true if the control with the given path has the error specified. Otherwise
@ -473,7 +474,7 @@ export abstract class AbstractControl {
* *
* If no path is given, it checks for the error on the present control. * If no path is given, it checks for the error on the present control.
*/ */
getError(errorCode: string, path: string[] = null): any { getError(errorCode: string, path?: string[]): any {
const control = path ? this.get(path) : this; const control = path ? this.get(path) : this;
return control && control._errors ? control._errors[errorCode] : null; return control && control._errors ? control._errors[errorCode] : null;
} }
@ -484,9 +485,7 @@ export abstract class AbstractControl {
* *
* If no path is given, it checks for the error on the present control. * If no path is given, it checks for the error on the present control.
*/ */
hasError(errorCode: string, path: string[] = null): boolean { hasError(errorCode: string, path?: string[]): boolean { return !!this.getError(errorCode, path); }
return !!this.getError(errorCode, path);
}
/** /**
* Retrieves the top-level ancestor of this control. * Retrieves the top-level ancestor of this control.
@ -635,8 +634,8 @@ export class FormControl extends AbstractControl {
_onChange: Function[] = []; _onChange: Function[] = [];
constructor( constructor(
formState: any = null, validator: ValidatorFn|ValidatorFn[] = null, formState: any = null, validator?: ValidatorFn|ValidatorFn[]|null,
asyncValidator: AsyncValidatorFn|AsyncValidatorFn[] = null) { asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]|null) {
super(coerceToValidator(validator), coerceToAsyncValidator(asyncValidator)); super(coerceToValidator(validator), coerceToAsyncValidator(asyncValidator));
this._applyFormState(formState); this._applyFormState(formState);
this.updateValueAndValidity({onlySelf: true, emitEvent: false}); this.updateValueAndValidity({onlySelf: true, emitEvent: false});
@ -831,9 +830,9 @@ export class FormControl extends AbstractControl {
*/ */
export class FormGroup extends AbstractControl { export class FormGroup extends AbstractControl {
constructor( constructor(
public controls: {[key: string]: AbstractControl}, validator: ValidatorFn = null, public controls: {[key: string]: AbstractControl}, validator?: ValidatorFn|null,
asyncValidator: AsyncValidatorFn = null) { asyncValidator?: AsyncValidatorFn|null) {
super(validator, asyncValidator); super(validator || null, asyncValidator || null);
this._initObservables(); this._initObservables();
this._setUpControls(); this._setUpControls();
this.updateValueAndValidity({onlySelf: true, emitEvent: false}); this.updateValueAndValidity({onlySelf: true, emitEvent: false});
@ -1137,9 +1136,9 @@ export class FormGroup extends AbstractControl {
*/ */
export class FormArray extends AbstractControl { export class FormArray extends AbstractControl {
constructor( constructor(
public controls: AbstractControl[], validator: ValidatorFn = null, public controls: AbstractControl[], validator?: ValidatorFn|null,
asyncValidator: AsyncValidatorFn = null) { asyncValidator?: AsyncValidatorFn|null) {
super(validator, asyncValidator); super(validator || null, asyncValidator || null);
this._initObservables(); this._initObservables();
this._setUpControls(); this._setUpControls();
this.updateValueAndValidity({onlySelf: true, emitEvent: false}); this.updateValueAndValidity({onlySelf: true, emitEvent: false});

View File

@ -143,9 +143,11 @@ export class Validators {
* Compose multiple validators into a single function that returns the union * Compose multiple validators into a single function that returns the union
* of the individual error maps. * of the individual error maps.
*/ */
static compose(validators: ValidatorFn[]): ValidatorFn { static compose(validators: null): null;
static compose(validators: (ValidatorFn|null|undefined)[]): ValidatorFn|null;
static compose(validators: (ValidatorFn|null|undefined)[]|null): ValidatorFn|null {
if (!validators) return null; if (!validators) return null;
const presentValidators = validators.filter(isPresent); const presentValidators: ValidatorFn[] = validators.filter(isPresent) as any;
if (presentValidators.length == 0) return null; if (presentValidators.length == 0) return null;
return function(control: AbstractControl) { return function(control: AbstractControl) {
@ -153,9 +155,9 @@ export class Validators {
}; };
} }
static composeAsync(validators: AsyncValidatorFn[]): AsyncValidatorFn { static composeAsync(validators: (AsyncValidatorFn|null)[]): AsyncValidatorFn|null {
if (!validators) return null; if (!validators) return null;
const presentValidators = validators.filter(isPresent); const presentValidators: AsyncValidatorFn[] = validators.filter(isPresent) as any;
if (presentValidators.length == 0) return null; if (presentValidators.length == 0) return null;
return function(control: AbstractControl) { return function(control: AbstractControl) {
@ -188,7 +190,7 @@ function _executeAsyncValidators(control: AbstractControl, validators: AsyncVali
function _mergeErrors(arrayOfErrors: ValidationErrors[]): ValidationErrors|null { function _mergeErrors(arrayOfErrors: ValidationErrors[]): ValidationErrors|null {
const res: {[key: string]: any} = const res: {[key: string]: any} =
arrayOfErrors.reduce((res: ValidationErrors | null, errors: ValidationErrors | null) => { arrayOfErrors.reduce((res: ValidationErrors | null, errors: ValidationErrors | null) => {
return errors != null ? {...res, ...errors} : res; return errors != null ? {...res !, ...errors} : res !;
}, {}); }, {});
return Object.keys(res).length === 0 ? null : res; return Object.keys(res).length === 0 ? null : res;
} }

View File

@ -28,7 +28,7 @@ class CustomValidatorDirective implements Validator {
function asyncValidator(expected: any, timeout = 0) { function asyncValidator(expected: any, timeout = 0) {
return (c: AbstractControl): any => { return (c: AbstractControl): any => {
let resolve: (result: any) => void; let resolve: (result: any) => void = undefined !;
const promise = new Promise(res => { resolve = res; }); const promise = new Promise(res => { resolve = res; });
const res = c.value != expected ? {'async': true} : null; const res = c.value != expected ? {'async': true} : null;
if (timeout == 0) { if (timeout == 0) {
@ -44,7 +44,7 @@ export function main() {
describe('Form Directives', () => { describe('Form Directives', () => {
let defaultAccessor: DefaultValueAccessor; let defaultAccessor: DefaultValueAccessor;
beforeEach(() => { defaultAccessor = new DefaultValueAccessor(null, null, null); }); beforeEach(() => { defaultAccessor = new DefaultValueAccessor(null !, null !, null !); });
describe('shared', () => { describe('shared', () => {
describe('selectValueAccessor', () => { describe('selectValueAccessor', () => {
@ -59,42 +59,42 @@ export function main() {
() => { expect(selectValueAccessor(dir, [defaultAccessor])).toEqual(defaultAccessor); }); () => { expect(selectValueAccessor(dir, [defaultAccessor])).toEqual(defaultAccessor); });
it('should return checkbox accessor when provided', () => { it('should return checkbox accessor when provided', () => {
const checkboxAccessor = new CheckboxControlValueAccessor(null, null); const checkboxAccessor = new CheckboxControlValueAccessor(null !, null !);
expect(selectValueAccessor(dir, [ expect(selectValueAccessor(dir, [
defaultAccessor, checkboxAccessor defaultAccessor, checkboxAccessor
])).toEqual(checkboxAccessor); ])).toEqual(checkboxAccessor);
}); });
it('should return select accessor when provided', () => { it('should return select accessor when provided', () => {
const selectAccessor = new SelectControlValueAccessor(null, null); const selectAccessor = new SelectControlValueAccessor(null !, null !);
expect(selectValueAccessor(dir, [ expect(selectValueAccessor(dir, [
defaultAccessor, selectAccessor defaultAccessor, selectAccessor
])).toEqual(selectAccessor); ])).toEqual(selectAccessor);
}); });
it('should return select multiple accessor when provided', () => { it('should return select multiple accessor when provided', () => {
const selectMultipleAccessor = new SelectMultipleControlValueAccessor(null, null); const selectMultipleAccessor = new SelectMultipleControlValueAccessor(null !, null !);
expect(selectValueAccessor(dir, [ expect(selectValueAccessor(dir, [
defaultAccessor, selectMultipleAccessor defaultAccessor, selectMultipleAccessor
])).toEqual(selectMultipleAccessor); ])).toEqual(selectMultipleAccessor);
}); });
it('should throw when more than one build-in accessor is provided', () => { it('should throw when more than one build-in accessor is provided', () => {
const checkboxAccessor = new CheckboxControlValueAccessor(null, null); const checkboxAccessor = new CheckboxControlValueAccessor(null !, null !);
const selectAccessor = new SelectControlValueAccessor(null, null); const selectAccessor = new SelectControlValueAccessor(null !, null !);
expect(() => selectValueAccessor(dir, [checkboxAccessor, selectAccessor])).toThrowError(); expect(() => selectValueAccessor(dir, [checkboxAccessor, selectAccessor])).toThrowError();
}); });
it('should return custom accessor when provided', () => { it('should return custom accessor when provided', () => {
const customAccessor = new SpyValueAccessor(); const customAccessor = new SpyValueAccessor();
const checkboxAccessor = new CheckboxControlValueAccessor(null, null); const checkboxAccessor = new CheckboxControlValueAccessor(null !, null !);
expect(selectValueAccessor(dir, <any>[defaultAccessor, customAccessor, checkboxAccessor])) expect(selectValueAccessor(dir, <any>[defaultAccessor, customAccessor, checkboxAccessor]))
.toEqual(customAccessor); .toEqual(customAccessor);
}); });
it('should return custom accessor when provided with select multiple', () => { it('should return custom accessor when provided with select multiple', () => {
const customAccessor = new SpyValueAccessor(); const customAccessor = new SpyValueAccessor();
const selectMultipleAccessor = new SelectMultipleControlValueAccessor(null, null); const selectMultipleAccessor = new SelectMultipleControlValueAccessor(null !, null !);
expect(selectValueAccessor( expect(selectValueAccessor(
dir, <any>[defaultAccessor, customAccessor, selectMultipleAccessor])) dir, <any>[defaultAccessor, customAccessor, selectMultipleAccessor]))
.toEqual(customAccessor); .toEqual(customAccessor);
@ -110,13 +110,13 @@ export function main() {
it('should compose functions', () => { it('should compose functions', () => {
const dummy1 = (_: any /** TODO #9100 */) => ({'dummy1': true}); const dummy1 = (_: any /** TODO #9100 */) => ({'dummy1': true});
const dummy2 = (_: any /** TODO #9100 */) => ({'dummy2': true}); const dummy2 = (_: any /** TODO #9100 */) => ({'dummy2': true});
const v = composeValidators([dummy1, dummy2]); const v = composeValidators([dummy1, dummy2]) !;
expect(v(new FormControl(''))).toEqual({'dummy1': true, 'dummy2': true}); expect(v(new FormControl(''))).toEqual({'dummy1': true, 'dummy2': true});
}); });
it('should compose validator directives', () => { it('should compose validator directives', () => {
const dummy1 = (_: any /** TODO #9100 */) => ({'dummy1': true}); const dummy1 = (_: any /** TODO #9100 */) => ({'dummy1': true});
const v = composeValidators([dummy1, new CustomValidatorDirective()]); const v = composeValidators([dummy1, new CustomValidatorDirective()]) !;
expect(v(new FormControl(''))).toEqual({'dummy1': true, 'custom': true}); expect(v(new FormControl(''))).toEqual({'dummy1': true, 'custom': true});
}); });
}); });
@ -168,7 +168,7 @@ export function main() {
describe('addControl', () => { describe('addControl', () => {
it('should throw when no control found', () => { it('should throw when no control found', () => {
const dir = new FormControlName(form, null, null, [defaultAccessor]); const dir = new FormControlName(form, null !, null !, [defaultAccessor]);
dir.name = 'invalidName'; dir.name = 'invalidName';
expect(() => form.addControl(dir)) expect(() => form.addControl(dir))
@ -176,7 +176,7 @@ export function main() {
}); });
it('should throw for a named control when no value accessor', () => { it('should throw for a named control when no value accessor', () => {
const dir = new FormControlName(form, null, null, null); const dir = new FormControlName(form, null !, null !, null !);
dir.name = 'login'; dir.name = 'login';
expect(() => form.addControl(dir)) expect(() => form.addControl(dir))
@ -184,8 +184,8 @@ export function main() {
}); });
it('should throw when no value accessor with path', () => { it('should throw when no value accessor with path', () => {
const group = new FormGroupName(form, null, null); const group = new FormGroupName(form, null !, null !);
const dir = new FormControlName(group, null, null, null); const dir = new FormControlName(group, null !, null !, null !);
group.name = 'passwords'; group.name = 'passwords';
dir.name = 'password'; dir.name = 'password';
@ -315,7 +315,7 @@ export function main() {
personControlGroupDir = new NgModelGroup(form, [], []); personControlGroupDir = new NgModelGroup(form, [], []);
personControlGroupDir.name = 'person'; personControlGroupDir.name = 'person';
loginControlDir = new NgModel(personControlGroupDir, null, null, [defaultAccessor]); loginControlDir = new NgModel(personControlGroupDir, null !, null !, [defaultAccessor]);
loginControlDir.name = 'login'; loginControlDir.name = 'login';
loginControlDir.valueAccessor = new DummyControlValueAccessor(); loginControlDir.valueAccessor = new DummyControlValueAccessor();
}); });
@ -534,7 +534,7 @@ export function main() {
beforeEach(() => { beforeEach(() => {
ngModel = new NgModel( ngModel = new NgModel(
null, [Validators.required], [asyncValidator('expected')], [defaultAccessor]); null !, [Validators.required], [asyncValidator('expected')], [defaultAccessor]);
ngModel.valueAccessor = new DummyControlValueAccessor(); ngModel.valueAccessor = new DummyControlValueAccessor();
control = ngModel.control; control = ngModel.control;
}); });
@ -566,7 +566,7 @@ export function main() {
}); });
it('should throw when no value accessor with named control', () => { it('should throw when no value accessor with named control', () => {
const namedDir = new NgModel(null, null, null, null); const namedDir = new NgModel(null !, null !, null !, null !);
namedDir.name = 'one'; namedDir.name = 'one';
expect(() => namedDir.ngOnChanges({})) expect(() => namedDir.ngOnChanges({}))
@ -574,7 +574,7 @@ export function main() {
}); });
it('should throw when no value accessor with unnamed control', () => { it('should throw when no value accessor with unnamed control', () => {
const unnamedDir = new NgModel(null, null, null, null); const unnamedDir = new NgModel(null !, null !, null !, null !);
expect(() => unnamedDir.ngOnChanges({})) expect(() => unnamedDir.ngOnChanges({}))
.toThrowError( .toThrowError(

View File

@ -15,7 +15,7 @@ import {Validators} from '../src/validators';
export function main() { export function main() {
function asyncValidator(expected: string, timeouts = {}) { function asyncValidator(expected: string, timeouts = {}) {
return (c: AbstractControl) => { return (c: AbstractControl) => {
let resolve: (result: any) => void; let resolve: (result: any) => void = undefined !;
const promise = new Promise(res => { resolve = res; }); const promise = new Promise(res => { resolve = res; });
const t = (timeouts as any)[c.value] != null ? (timeouts as any)[c.value] : 0; const t = (timeouts as any)[c.value] != null ? (timeouts as any)[c.value] : 0;
const res = c.value != expected ? {'async': true} : null; const res = c.value != expected ? {'async': true} : null;
@ -89,7 +89,7 @@ export function main() {
new FormGroup({'c2': new FormControl('v2'), 'c3': new FormControl('v3')}), new FormGroup({'c2': new FormControl('v2'), 'c3': new FormControl('v3')}),
new FormArray([new FormControl('v4'), new FormControl('v5')]) new FormArray([new FormControl('v4'), new FormControl('v5')])
]); ]);
a.at(0).get('c3').disable(); a.at(0).get('c3') !.disable();
(a.at(1) as FormArray).at(1).disable(); (a.at(1) as FormArray).at(1).disable();
expect(a.getRawValue()).toEqual([{'c2': 'v2', 'c3': 'v3'}, ['v4', 'v5']]); expect(a.getRawValue()).toEqual([{'c2': 'v2', 'c3': 'v3'}, ['v4', 'v5']]);
@ -693,7 +693,7 @@ export function main() {
describe('get', () => { describe('get', () => {
it('should return null when path is null', () => { it('should return null when path is null', () => {
const g = new FormGroup({}); const g = new FormGroup({});
expect(g.get(null)).toEqual(null); expect(g.get(null !)).toEqual(null);
}); });
it('should return null when path is empty', () => { it('should return null when path is empty', () => {
@ -712,23 +712,23 @@ export function main() {
'nested': new FormGroup({'two': new FormControl('222')}) 'nested': new FormGroup({'two': new FormControl('222')})
}); });
expect(g.get(['one']).value).toEqual('111'); expect(g.get(['one']) !.value).toEqual('111');
expect(g.get('one').value).toEqual('111'); expect(g.get('one') !.value).toEqual('111');
expect(g.get(['nested', 'two']).value).toEqual('222'); expect(g.get(['nested', 'two']) !.value).toEqual('222');
expect(g.get('nested.two').value).toEqual('222'); expect(g.get('nested.two') !.value).toEqual('222');
}); });
it('should return an element of an array', () => { it('should return an element of an array', () => {
const g = new FormGroup({'array': new FormArray([new FormControl('111')])}); const g = new FormGroup({'array': new FormArray([new FormControl('111')])});
expect(g.get(['array', 0]).value).toEqual('111'); expect(g.get(['array', 0]) !.value).toEqual('111');
}); });
}); });
describe('asyncValidator', () => { describe('asyncValidator', () => {
it('should run the async validator', fakeAsync(() => { it('should run the async validator', fakeAsync(() => {
const c = new FormControl('value'); const c = new FormControl('value');
const g = new FormArray([c], null, asyncValidator('expected')); const g = new FormArray([c], null !, asyncValidator('expected'));
expect(g.pending).toEqual(true); expect(g.pending).toEqual(true);
@ -793,10 +793,10 @@ export function main() {
}); });
expect(g.valid).toBe(false); expect(g.valid).toBe(false);
g.get('nested').disable(); g.get('nested') !.disable();
expect(g.valid).toBe(true); expect(g.valid).toBe(true);
g.get('nested').enable(); g.get('nested') !.enable();
expect(g.valid).toBe(false); expect(g.valid).toBe(false);
}); });
@ -805,36 +805,36 @@ export function main() {
{nested: new FormArray([new FormControl('one')]), two: new FormControl('two')}); {nested: new FormArray([new FormControl('one')]), two: new FormControl('two')});
expect(g.value).toEqual({'nested': ['one'], 'two': 'two'}); expect(g.value).toEqual({'nested': ['one'], 'two': 'two'});
g.get('nested').disable(); g.get('nested') !.disable();
expect(g.value).toEqual({'two': 'two'}); expect(g.value).toEqual({'two': 'two'});
g.get('nested').enable(); g.get('nested') !.enable();
expect(g.value).toEqual({'nested': ['one'], 'two': 'two'}); expect(g.value).toEqual({'nested': ['one'], 'two': 'two'});
}); });
it('should ignore disabled controls when determining dirtiness', () => { it('should ignore disabled controls when determining dirtiness', () => {
const g = new FormGroup({nested: a, two: new FormControl('two')}); const g = new FormGroup({nested: a, two: new FormControl('two')});
g.get(['nested', 0]).markAsDirty(); g.get(['nested', 0]) !.markAsDirty();
expect(g.dirty).toBe(true); expect(g.dirty).toBe(true);
g.get('nested').disable(); g.get('nested') !.disable();
expect(g.get('nested').dirty).toBe(true); expect(g.get('nested') !.dirty).toBe(true);
expect(g.dirty).toEqual(false); expect(g.dirty).toEqual(false);
g.get('nested').enable(); g.get('nested') !.enable();
expect(g.dirty).toEqual(true); expect(g.dirty).toEqual(true);
}); });
it('should ignore disabled controls when determining touched state', () => { it('should ignore disabled controls when determining touched state', () => {
const g = new FormGroup({nested: a, two: new FormControl('two')}); const g = new FormGroup({nested: a, two: new FormControl('two')});
g.get(['nested', 0]).markAsTouched(); g.get(['nested', 0]) !.markAsTouched();
expect(g.touched).toBe(true); expect(g.touched).toBe(true);
g.get('nested').disable(); g.get('nested') !.disable();
expect(g.get('nested').touched).toBe(true); expect(g.get('nested') !.touched).toBe(true);
expect(g.touched).toEqual(false); expect(g.touched).toEqual(false);
g.get('nested').enable(); g.get('nested') !.enable();
expect(g.touched).toEqual(true); expect(g.touched).toEqual(true);
}); });
@ -901,7 +901,7 @@ export function main() {
}); });
it('should clear out async array errors when disabled', fakeAsync(() => { it('should clear out async array errors when disabled', fakeAsync(() => {
const arr = new FormArray([new FormControl()], null, asyncValidator('expected')); const arr = new FormArray([new FormControl()], null !, asyncValidator('expected'));
tick(); tick();
expect(arr.errors).toEqual({'async': true}); expect(arr.errors).toEqual({'async': true});
@ -914,7 +914,7 @@ export function main() {
})); }));
it('should re-populate async array errors when enabled from a child', fakeAsync(() => { it('should re-populate async array errors when enabled from a child', fakeAsync(() => {
const arr = new FormArray([new FormControl()], null, asyncValidator('expected')); const arr = new FormArray([new FormControl()], null !, asyncValidator('expected'));
tick(); tick();
expect(arr.errors).toEqual({'async': true}); expect(arr.errors).toEqual({'async': true});
@ -988,7 +988,7 @@ export function main() {
}); });
it('should remove control if new control is null', () => { it('should remove control if new control is null', () => {
a.setControl(0, null); a.setControl(0, null !);
expect(a.controls[0]).not.toBeDefined(); expect(a.controls[0]).not.toBeDefined();
expect(a.value).toEqual([]); expect(a.value).toEqual([]);
}); });

View File

@ -16,7 +16,7 @@ import {FormArray} from '../src/model';
export function main() { export function main() {
function asyncValidator(expected: string, timeouts = {}) { function asyncValidator(expected: string, timeouts = {}) {
return (c: FormControl) => { return (c: FormControl) => {
let resolve: (result: any) => void; let resolve: (result: any) => void = undefined !;
const promise = new Promise(res => { resolve = res; }); const promise = new Promise(res => { resolve = res; });
const t = (timeouts as any)[c.value] != null ? (timeouts as any)[c.value] : 0; const t = (timeouts as any)[c.value] != null ? (timeouts as any)[c.value] : 0;
const res = c.value != expected ? {'async': true} : null; const res = c.value != expected ? {'async': true} : null;
@ -49,7 +49,7 @@ export function main() {
describe('boxed values', () => { describe('boxed values', () => {
it('should support valid boxed values on creation', () => { it('should support valid boxed values on creation', () => {
const c = new FormControl({value: 'some val', disabled: true}, null, null); const c = new FormControl({value: 'some val', disabled: true}, null !, null !);
expect(c.disabled).toBe(true); expect(c.disabled).toBe(true);
expect(c.value).toBe('some val'); expect(c.value).toBe('some val');
expect(c.status).toBe('DISABLED'); expect(c.status).toBe('DISABLED');
@ -63,13 +63,13 @@ export function main() {
}); });
it('should not treat objects as boxed values if they have more than two props', () => { it('should not treat objects as boxed values if they have more than two props', () => {
const c = new FormControl({value: '', disabled: true, test: 'test'}, null, null); const c = new FormControl({value: '', disabled: true, test: 'test'}, null !, null !);
expect(c.value).toEqual({value: '', disabled: true, test: 'test'}); expect(c.value).toEqual({value: '', disabled: true, test: 'test'});
expect(c.disabled).toBe(false); expect(c.disabled).toBe(false);
}); });
it('should not treat objects as boxed values if disabled is missing', () => { it('should not treat objects as boxed values if disabled is missing', () => {
const c = new FormControl({value: '', test: 'test'}, null, null); const c = new FormControl({value: '', test: 'test'}, null !, null !);
expect(c.value).toEqual({value: '', test: 'test'}); expect(c.value).toEqual({value: '', test: 'test'});
expect(c.disabled).toBe(false); expect(c.disabled).toBe(false);
}); });
@ -156,7 +156,7 @@ export function main() {
describe('asyncValidator', () => { describe('asyncValidator', () => {
it('should run validator with the initial value', fakeAsync(() => { it('should run validator with the initial value', fakeAsync(() => {
const c = new FormControl('value', null, asyncValidator('expected')); const c = new FormControl('value', null !, asyncValidator('expected'));
tick(); tick();
expect(c.valid).toEqual(false); expect(c.valid).toEqual(false);
@ -164,7 +164,7 @@ export function main() {
})); }));
it('should support validators returning observables', fakeAsync(() => { it('should support validators returning observables', fakeAsync(() => {
const c = new FormControl('value', null, asyncValidatorReturningObservable); const c = new FormControl('value', null !, asyncValidatorReturningObservable);
tick(); tick();
expect(c.valid).toEqual(false); expect(c.valid).toEqual(false);
@ -172,7 +172,7 @@ export function main() {
})); }));
it('should rerun the validator when the value changes', fakeAsync(() => { it('should rerun the validator when the value changes', fakeAsync(() => {
const c = new FormControl('value', null, asyncValidator('expected')); const c = new FormControl('value', null !, asyncValidator('expected'));
c.setValue('expected'); c.setValue('expected');
tick(); tick();
@ -193,7 +193,7 @@ export function main() {
})); }));
it('should mark the control as pending while running the async validation', fakeAsync(() => { it('should mark the control as pending while running the async validation', fakeAsync(() => {
const c = new FormControl('', null, asyncValidator('expected')); const c = new FormControl('', null !, asyncValidator('expected'));
expect(c.pending).toEqual(true); expect(c.pending).toEqual(true);
@ -204,7 +204,7 @@ export function main() {
it('should only use the latest async validation run', fakeAsync(() => { it('should only use the latest async validation run', fakeAsync(() => {
const c = new FormControl( const c = new FormControl(
'', null, asyncValidator('expected', {'long': 200, 'expected': 100})); '', null !, asyncValidator('expected', {'long': 200, 'expected': 100}));
c.setValue('long'); c.setValue('long');
c.setValue('expected'); c.setValue('expected');
@ -216,14 +216,14 @@ export function main() {
it('should support arrays of async validator functions if passed', fakeAsync(() => { it('should support arrays of async validator functions if passed', fakeAsync(() => {
const c = const c =
new FormControl('value', null, [asyncValidator('expected'), otherAsyncValidator]); new FormControl('value', null !, [asyncValidator('expected'), otherAsyncValidator]);
tick(); tick();
expect(c.errors).toEqual({'async': true, 'other': true}); expect(c.errors).toEqual({'async': true, 'other': true});
})); }));
it('should add single async validator', fakeAsync(() => { it('should add single async validator', fakeAsync(() => {
const c = new FormControl('value', null); const c = new FormControl('value', null !);
c.setAsyncValidators(asyncValidator('expected')); c.setAsyncValidators(asyncValidator('expected'));
expect(c.asyncValidator).not.toEqual(null); expect(c.asyncValidator).not.toEqual(null);
@ -235,7 +235,7 @@ export function main() {
})); }));
it('should add async validator from array', fakeAsync(() => { it('should add async validator from array', fakeAsync(() => {
const c = new FormControl('value', null); const c = new FormControl('value', null !);
c.setAsyncValidators([asyncValidator('expected')]); c.setAsyncValidators([asyncValidator('expected')]);
expect(c.asyncValidator).not.toEqual(null); expect(c.asyncValidator).not.toEqual(null);
@ -634,8 +634,7 @@ export function main() {
tick(); tick();
expect(log).toEqual([ expect(log).toEqual([
'' + 'value: \'\'',
'value: \'\'',
'status: \'INVALID\'', 'status: \'INVALID\'',
'value: \'nonEmpty\'', 'value: \'nonEmpty\'',
'status: \'PENDING\'', 'status: \'PENDING\'',
@ -935,7 +934,7 @@ export function main() {
}); });
it('should clear out async errors when disabled', fakeAsync(() => { it('should clear out async errors when disabled', fakeAsync(() => {
const c = new FormControl('', null, asyncValidator('expected')); const c = new FormControl('', null !, asyncValidator('expected'));
tick(); tick();
expect(c.errors).toEqual({'async': true}); expect(c.errors).toEqual({'async': true});

View File

@ -15,7 +15,7 @@ import {AbstractControl, FormArray, FormControl, FormGroup, Validators} from '@a
export function main() { export function main() {
function asyncValidator(expected: string, timeouts = {}) { function asyncValidator(expected: string, timeouts = {}) {
return (c: AbstractControl) => { return (c: AbstractControl) => {
let resolve: (result: any) => void; let resolve: (result: any) => void = undefined !;
const promise = new Promise(res => { resolve = res; }); const promise = new Promise(res => { resolve = res; });
const t = (timeouts as any)[c.value] != null ? (timeouts as any)[c.value] : 0; const t = (timeouts as any)[c.value] != null ? (timeouts as any)[c.value] : 0;
const res = c.value != expected ? {'async': true} : null; const res = c.value != expected ? {'async': true} : null;
@ -70,7 +70,7 @@ export function main() {
'group': new FormGroup({'c2': new FormControl('v2'), 'c3': new FormControl('v3')}), 'group': new FormGroup({'c2': new FormControl('v2'), 'c3': new FormControl('v3')}),
'array': new FormArray([new FormControl('v4'), new FormControl('v5')]) 'array': new FormArray([new FormControl('v4'), new FormControl('v5')])
}); });
fg.get('group').get('c3').disable(); fg.get('group') !.get('c3') !.disable();
(fg.get('array') as FormArray).at(1).disable(); (fg.get('array') as FormArray).at(1).disable();
expect(fg.getRawValue()) expect(fg.getRawValue())
@ -690,7 +690,7 @@ export function main() {
describe('asyncValidator', () => { describe('asyncValidator', () => {
it('should run the async validator', fakeAsync(() => { it('should run the async validator', fakeAsync(() => {
const c = new FormControl('value'); const c = new FormControl('value');
const g = new FormGroup({'one': c}, null, asyncValidator('expected')); const g = new FormGroup({'one': c}, null !, asyncValidator('expected'));
expect(g.pending).toEqual(true); expect(g.pending).toEqual(true);
@ -701,7 +701,7 @@ export function main() {
})); }));
it('should set the parent group\'s status to pending', fakeAsync(() => { it('should set the parent group\'s status to pending', fakeAsync(() => {
const c = new FormControl('value', null, asyncValidator('expected')); const c = new FormControl('value', null !, asyncValidator('expected'));
const g = new FormGroup({'one': c}); const g = new FormGroup({'one': c});
expect(g.pending).toEqual(true); expect(g.pending).toEqual(true);
@ -713,13 +713,13 @@ export function main() {
it('should run the parent group\'s async validator when children are pending', it('should run the parent group\'s async validator when children are pending',
fakeAsync(() => { fakeAsync(() => {
const c = new FormControl('value', null, asyncValidator('expected')); const c = new FormControl('value', null !, asyncValidator('expected'));
const g = new FormGroup({'one': c}, null, asyncValidator('expected')); const g = new FormGroup({'one': c}, null !, asyncValidator('expected'));
tick(1); tick(1);
expect(g.errors).toEqual({'async': true}); expect(g.errors).toEqual({'async': true});
expect(g.get('one').errors).toEqual({'async': true}); expect(g.get('one') !.errors).toEqual({'async': true});
})); }));
}); });
@ -772,10 +772,10 @@ export function main() {
}); });
expect(g.valid).toBe(false); expect(g.valid).toBe(false);
g.get('nested').disable(); g.get('nested') !.disable();
expect(g.valid).toBe(true); expect(g.valid).toBe(true);
g.get('nested').enable(); g.get('nested') !.enable();
expect(g.valid).toBe(false); expect(g.valid).toBe(false);
}); });
@ -784,10 +784,10 @@ export function main() {
{nested: new FormGroup({one: new FormControl('one')}), two: new FormControl('two')}); {nested: new FormGroup({one: new FormControl('one')}), two: new FormControl('two')});
expect(g.value).toEqual({'nested': {'one': 'one'}, 'two': 'two'}); expect(g.value).toEqual({'nested': {'one': 'one'}, 'two': 'two'});
g.get('nested').disable(); g.get('nested') !.disable();
expect(g.value).toEqual({'two': 'two'}); expect(g.value).toEqual({'two': 'two'});
g.get('nested').enable(); g.get('nested') !.enable();
expect(g.value).toEqual({'nested': {'one': 'one'}, 'two': 'two'}); expect(g.value).toEqual({'nested': {'one': 'one'}, 'two': 'two'});
}); });
@ -795,13 +795,13 @@ export function main() {
const g = new FormGroup( const g = new FormGroup(
{nested: new FormGroup({one: new FormControl('one'), two: new FormControl('two')})}); {nested: new FormGroup({one: new FormControl('one'), two: new FormControl('two')})});
g.get('nested.two').disable(); g.get('nested.two') !.disable();
expect(g.value).toEqual({nested: {one: 'one'}}); expect(g.value).toEqual({nested: {one: 'one'}});
g.get('nested').disable(); g.get('nested') !.disable();
expect(g.value).toEqual({nested: {one: 'one', two: 'two'}}); expect(g.value).toEqual({nested: {one: 'one', two: 'two'}});
g.get('nested').enable(); g.get('nested') !.enable();
expect(g.value).toEqual({nested: {one: 'one', two: 'two'}}); expect(g.value).toEqual({nested: {one: 'one', two: 'two'}});
}); });
@ -809,38 +809,38 @@ export function main() {
const g = new FormGroup( const g = new FormGroup(
{nested: new FormGroup({one: new FormControl('one'), two: new FormControl('two')})}); {nested: new FormGroup({one: new FormControl('one'), two: new FormControl('two')})});
g.get('nested.two').disable(); g.get('nested.two') !.disable();
expect(g.value).toEqual({nested: {one: 'one'}}); expect(g.value).toEqual({nested: {one: 'one'}});
g.get('nested').enable(); g.get('nested') !.enable();
expect(g.value).toEqual({nested: {one: 'one', two: 'two'}}); expect(g.value).toEqual({nested: {one: 'one', two: 'two'}});
}); });
it('should ignore disabled controls when determining dirtiness', () => { it('should ignore disabled controls when determining dirtiness', () => {
const g = new FormGroup( const g = new FormGroup(
{nested: new FormGroup({one: new FormControl('one')}), two: new FormControl('two')}); {nested: new FormGroup({one: new FormControl('one')}), two: new FormControl('two')});
g.get('nested.one').markAsDirty(); g.get('nested.one') !.markAsDirty();
expect(g.dirty).toBe(true); expect(g.dirty).toBe(true);
g.get('nested').disable(); g.get('nested') !.disable();
expect(g.get('nested').dirty).toBe(true); expect(g.get('nested') !.dirty).toBe(true);
expect(g.dirty).toEqual(false); expect(g.dirty).toEqual(false);
g.get('nested').enable(); g.get('nested') !.enable();
expect(g.dirty).toEqual(true); expect(g.dirty).toEqual(true);
}); });
it('should ignore disabled controls when determining touched state', () => { it('should ignore disabled controls when determining touched state', () => {
const g = new FormGroup( const g = new FormGroup(
{nested: new FormGroup({one: new FormControl('one')}), two: new FormControl('two')}); {nested: new FormGroup({one: new FormControl('one')}), two: new FormControl('two')});
g.get('nested.one').markAsTouched(); g.get('nested.one') !.markAsTouched();
expect(g.touched).toBe(true); expect(g.touched).toBe(true);
g.get('nested').disable(); g.get('nested') !.disable();
expect(g.get('nested').touched).toBe(true); expect(g.get('nested') !.touched).toBe(true);
expect(g.touched).toEqual(false); expect(g.touched).toEqual(false);
g.get('nested').enable(); g.get('nested') !.enable();
expect(g.touched).toEqual(true); expect(g.touched).toEqual(true);
}); });
@ -907,7 +907,8 @@ export function main() {
}); });
it('should clear out async group errors when disabled', fakeAsync(() => { it('should clear out async group errors when disabled', fakeAsync(() => {
const g = new FormGroup({'one': new FormControl()}, null, asyncValidator('expected')); const g =
new FormGroup({'one': new FormControl()}, null !, asyncValidator('expected'));
tick(); tick();
expect(g.errors).toEqual({'async': true}); expect(g.errors).toEqual({'async': true});
@ -920,7 +921,8 @@ export function main() {
})); }));
it('should re-populate async group errors when enabled from a child', fakeAsync(() => { it('should re-populate async group errors when enabled from a child', fakeAsync(() => {
const g = new FormGroup({'one': new FormControl()}, null, asyncValidator('expected')); const g =
new FormGroup({'one': new FormControl()}, null !, asyncValidator('expected'));
tick(); tick();
expect(g.errors).toEqual({'async': true}); expect(g.errors).toEqual({'async': true});
@ -1028,7 +1030,7 @@ export function main() {
}); });
it('should remove control if new control is null', () => { it('should remove control if new control is null', () => {
g.setControl('one', null); g.setControl('one', null !);
expect(g.controls['one']).not.toBeDefined(); expect(g.controls['one']).not.toBeDefined();
expect(g.value).toEqual({}); expect(g.value).toEqual({});
}); });

View File

@ -166,7 +166,7 @@ export function main() {
}); });
fixture.componentInstance.form = form; fixture.componentInstance.form = form;
fixture.detectChanges(); fixture.detectChanges();
expect(form.get('login').errors).toEqual({required: true}); expect(form.get('login') !.errors).toEqual({required: true});
const newForm = new FormGroup({ const newForm = new FormGroup({
'login': new FormControl(''), 'login': new FormControl(''),
@ -177,7 +177,7 @@ export function main() {
fixture.componentInstance.form = newForm; fixture.componentInstance.form = newForm;
fixture.detectChanges(); fixture.detectChanges();
expect(newForm.get('login').errors).toEqual({required: true}); expect(newForm.get('login') !.errors).toEqual({required: true});
}); });
it('should pick up dir validators from nested form groups', () => { it('should pick up dir validators from nested form groups', () => {
@ -188,7 +188,7 @@ export function main() {
}); });
fixture.componentInstance.form = form; fixture.componentInstance.form = form;
fixture.detectChanges(); fixture.detectChanges();
expect(form.get('signin').valid).toBe(false); expect(form.get('signin') !.valid).toBe(false);
const newForm = new FormGroup({ const newForm = new FormGroup({
'signin': 'signin':
@ -197,7 +197,7 @@ export function main() {
fixture.componentInstance.form = newForm; fixture.componentInstance.form = newForm;
fixture.detectChanges(); fixture.detectChanges();
expect(form.get('signin').valid).toBe(false); expect(form.get('signin') !.valid).toBe(false);
}); });
it('should strip named controls that are not found', () => { it('should strip named controls that are not found', () => {
@ -373,7 +373,7 @@ export function main() {
it('should throw an error if compareWith is not a function', () => { it('should throw an error if compareWith is not a function', () => {
const fixture = initTest(FormControlSelectWithCompareFn); const fixture = initTest(FormControlSelectWithCompareFn);
fixture.componentInstance.compareFn = null; fixture.componentInstance.compareFn = null !;
expect(() => fixture.detectChanges()) expect(() => fixture.detectChanges())
.toThrowError(/compareWith must be a function, but received null/); .toThrowError(/compareWith must be a function, but received null/);
}); });
@ -412,7 +412,7 @@ export function main() {
it('should throw an error when compareWith is not a function', () => { it('should throw an error when compareWith is not a function', () => {
const fixture = initTest(FormControlSelectMultipleWithCompareFn); const fixture = initTest(FormControlSelectMultipleWithCompareFn);
fixture.componentInstance.compareFn = null; fixture.componentInstance.compareFn = null !;
expect(() => fixture.detectChanges()) expect(() => fixture.detectChanges())
.toThrowError(/compareWith must be a function, but received null/); .toThrowError(/compareWith must be a function, but received null/);
}); });
@ -623,7 +623,7 @@ export function main() {
it('should emit ngSubmit event with the original submit event on submit', () => { it('should emit ngSubmit event with the original submit event on submit', () => {
const fixture = initTest(FormGroupComp); const fixture = initTest(FormGroupComp);
fixture.componentInstance.form = new FormGroup({'login': new FormControl('loginValue')}); fixture.componentInstance.form = new FormGroup({'login': new FormControl('loginValue')});
fixture.componentInstance.event = null; fixture.componentInstance.event = null !;
fixture.detectChanges(); fixture.detectChanges();
const formEl = fixture.debugElement.query(By.css('form')).nativeElement; const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
@ -739,7 +739,7 @@ export function main() {
it('should work with single fields and async validators', fakeAsync(() => { it('should work with single fields and async validators', fakeAsync(() => {
const fixture = initTest(FormControlComp); const fixture = initTest(FormControlComp);
const control = new FormControl('', null, uniqLoginAsyncValidator('good')); const control = new FormControl('', null !, uniqLoginAsyncValidator('good'));
fixture.debugElement.componentInstance.control = control; fixture.debugElement.componentInstance.control = control;
fixture.detectChanges(); fixture.detectChanges();
@ -995,10 +995,10 @@ export function main() {
fixture.detectChanges(); fixture.detectChanges();
// view -> model // view -> model
expect(form.get('food').value).toEqual('chicken'); expect(form.get('food') !.value).toEqual('chicken');
expect(inputs[1].nativeElement.checked).toEqual(false); expect(inputs[1].nativeElement.checked).toEqual(false);
form.get('food').setValue('fish'); form.get('food') !.setValue('fish');
fixture.detectChanges(); fixture.detectChanges();
// programmatic change -> view // programmatic change -> view
@ -1039,16 +1039,16 @@ export function main() {
fixture.componentInstance.form = form; fixture.componentInstance.form = form;
fixture.detectChanges(); fixture.detectChanges();
form.get('food').setValue(null); form.get('food') !.setValue(null);
fixture.detectChanges(); fixture.detectChanges();
const inputs = fixture.debugElement.queryAll(By.css('input')); const inputs = fixture.debugElement.queryAll(By.css('input'));
expect(inputs[0].nativeElement.checked).toEqual(false); expect(inputs[0].nativeElement.checked).toEqual(false);
form.get('food').setValue('chicken'); form.get('food') !.setValue('chicken');
fixture.detectChanges(); fixture.detectChanges();
form.get('food').setValue(undefined); form.get('food') !.setValue(undefined);
fixture.detectChanges(); fixture.detectChanges();
expect(inputs[0].nativeElement.checked).toEqual(false); expect(inputs[0].nativeElement.checked).toEqual(false);
}); });
@ -1139,8 +1139,8 @@ export function main() {
fixture.detectChanges(); fixture.detectChanges();
// view -> model // view -> model
expect(form.get('food').value).toEqual('chicken'); expect(form.get('food') !.value).toEqual('chicken');
expect(form.get('nested.food').value).toEqual('fish'); expect(form.get('nested.food') !.value).toEqual('fish');
expect(inputs[1].nativeElement.checked).toEqual(false); expect(inputs[1].nativeElement.checked).toEqual(false);
expect(inputs[2].nativeElement.checked).toEqual(false); expect(inputs[2].nativeElement.checked).toEqual(false);
@ -1161,7 +1161,7 @@ export function main() {
expect(inputs[2].nativeElement.disabled).toEqual(false); expect(inputs[2].nativeElement.disabled).toEqual(false);
expect(inputs[3].nativeElement.disabled).toEqual(false); expect(inputs[3].nativeElement.disabled).toEqual(false);
form.get('food').disable(); form.get('food') !.disable();
expect(inputs[0].nativeElement.disabled).toEqual(true); expect(inputs[0].nativeElement.disabled).toEqual(true);
expect(inputs[1].nativeElement.disabled).toEqual(true); expect(inputs[1].nativeElement.disabled).toEqual(true);
expect(inputs[2].nativeElement.disabled).toEqual(false); expect(inputs[2].nativeElement.disabled).toEqual(false);
@ -1267,9 +1267,9 @@ export function main() {
expect(form.value).toEqual({'login': 'bb'}); expect(form.value).toEqual({'login': 'bb'});
// custom validator // custom validator
expect(form.get('login').errors).toEqual({'err': true}); expect(form.get('login') !.errors).toEqual({'err': true});
form.setValue({login: 'expected'}); form.setValue({login: 'expected'});
expect(form.get('login').errors).toEqual(null); expect(form.get('login') !.errors).toEqual(null);
}); });
it('should support non builtin input elements that fire a change event without a \'target\' property', it('should support non builtin input elements that fire a change event without a \'target\' property',
@ -1295,7 +1295,7 @@ export function main() {
}); });
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.componentInstance.form.status).toEqual('DISABLED'); expect(fixture.componentInstance.form.status).toEqual('DISABLED');
expect(fixture.componentInstance.form.get('login').status).toEqual('DISABLED'); expect(fixture.componentInstance.form.get('login') !.status).toEqual('DISABLED');
}); });
it('should support custom accessors without setDisabledState - formControlDirective', it('should support custom accessors without setDisabledState - formControlDirective',
@ -1539,9 +1539,9 @@ export function main() {
.toEqual(pattern.nativeElement.getAttribute('pattern')); .toEqual(pattern.nativeElement.getAttribute('pattern'));
fixture.componentInstance.required = false; fixture.componentInstance.required = false;
fixture.componentInstance.minLen = null; fixture.componentInstance.minLen = null !;
fixture.componentInstance.maxLen = null; fixture.componentInstance.maxLen = null !;
fixture.componentInstance.pattern = null; fixture.componentInstance.pattern = null !;
fixture.detectChanges(); fixture.detectChanges();
expect(form.hasError('required', ['login'])).toEqual(false); expect(form.hasError('required', ['login'])).toEqual(false);
@ -1581,9 +1581,9 @@ export function main() {
fixture.detectChanges(); fixture.detectChanges();
fixture.componentInstance.required = false; fixture.componentInstance.required = false;
fixture.componentInstance.minLen = null; fixture.componentInstance.minLen = null !;
fixture.componentInstance.maxLen = null; fixture.componentInstance.maxLen = null !;
fixture.componentInstance.pattern = null; fixture.componentInstance.pattern = null !;
fixture.detectChanges(); fixture.detectChanges();
expect(newForm.hasError('required', ['login'])).toEqual(false); expect(newForm.hasError('required', ['login'])).toEqual(false);
@ -1681,7 +1681,7 @@ export function main() {
const fixture = initTest(FormControlComp); const fixture = initTest(FormControlComp);
const resultArr: number[] = []; const resultArr: number[] = [];
fixture.componentInstance.control = fixture.componentInstance.control =
new FormControl('', null, observableValidator(resultArr)); new FormControl('', null !, observableValidator(resultArr));
fixture.detectChanges(); fixture.detectChanges();
tick(100); tick(100);

View File

@ -107,9 +107,9 @@ export function main() {
tick(); tick();
const form = fixture.debugElement.children[0].injector.get(NgForm); const form = fixture.debugElement.children[0].injector.get(NgForm);
expect(form.control.get('name').value).toEqual({first: 'Nancy', last: 'Drew'}); expect(form.control.get('name') !.value).toEqual({first: 'Nancy', last: 'Drew'});
expect(form.control.get('name.first').value).toEqual('Nancy'); expect(form.control.get('name.first') !.value).toEqual('Nancy');
expect(form.control.get('email').value).toEqual('some email'); expect(form.control.get('email') !.value).toEqual('some email');
})); }));
it('should remove controls and control groups from form control model', fakeAsync(() => { it('should remove controls and control groups from form control model', fakeAsync(() => {
@ -121,7 +121,7 @@ export function main() {
tick(); tick();
const form = fixture.debugElement.children[0].injector.get(NgForm); const form = fixture.debugElement.children[0].injector.get(NgForm);
expect(form.control.get('email').value).toEqual('some email'); expect(form.control.get('email') !.value).toEqual('some email');
expect(form.value).toEqual({name: {first: 'Nancy'}, email: 'some email'}); expect(form.value).toEqual({name: {first: 'Nancy'}, email: 'some email'});
// should remove individual control successfully // should remove individual control successfully
@ -132,8 +132,8 @@ export function main() {
expect(form.control.get('email')).toBe(null); expect(form.control.get('email')).toBe(null);
expect(form.value).toEqual({name: {first: 'Nancy'}}); expect(form.value).toEqual({name: {first: 'Nancy'}});
expect(form.control.get('name').value).toEqual({first: 'Nancy'}); expect(form.control.get('name') !.value).toEqual({first: 'Nancy'});
expect(form.control.get('name.first').value).toEqual('Nancy'); expect(form.control.get('name.first') !.value).toEqual('Nancy');
// should remove form group successfully // should remove form group successfully
fixture.componentInstance.groupShowing = false; fixture.componentInstance.groupShowing = false;
@ -228,7 +228,7 @@ export function main() {
it('should not create a template-driven form when ngNoForm is used', () => { it('should not create a template-driven form when ngNoForm is used', () => {
const fixture = initTest(NgNoFormComp); const fixture = initTest(NgNoFormComp);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.children[0].providerTokens.length).toEqual(0); expect(fixture.debugElement.children[0].providerTokens !.length).toEqual(0);
}); });
it('should not add novalidate when ngNoForm is used', () => { it('should not add novalidate when ngNoForm is used', () => {
@ -282,7 +282,7 @@ export function main() {
describe('submit and reset events', () => { describe('submit and reset events', () => {
it('should emit ngSubmit event with the original submit event on submit', fakeAsync(() => { it('should emit ngSubmit event with the original submit event on submit', fakeAsync(() => {
const fixture = initTest(NgModelForm); const fixture = initTest(NgModelForm);
fixture.componentInstance.event = null; fixture.componentInstance.event = null !;
const form = fixture.debugElement.query(By.css('form')); const form = fixture.debugElement.query(By.css('form'));
dispatchEvent(form.nativeElement, 'submit'); dispatchEvent(form.nativeElement, 'submit');
@ -355,11 +355,11 @@ export function main() {
expect(form.valid).toEqual(true); expect(form.valid).toEqual(true);
expect(form.value).toEqual({}); expect(form.value).toEqual({});
let formValidity: string; let formValidity: string = undefined !;
let formValue: Object; let formValue: Object = undefined !;
form.statusChanges.subscribe((status: string) => formValidity = status); form.statusChanges !.subscribe((status: string) => formValidity = status);
form.valueChanges.subscribe((value: string) => formValue = value); form.valueChanges !.subscribe((value: string) => formValue = value);
tick(); tick();
@ -374,8 +374,8 @@ export function main() {
fixture.detectChanges(); fixture.detectChanges();
tick(); tick();
form.get('name').valueChanges.subscribe( form.get('name') !.valueChanges.subscribe(
() => { expect(form.get('name').dirty).toBe(true); }); () => { expect(form.get('name') !.dirty).toBe(true); });
const inputEl = fixture.debugElement.query(By.css('input')).nativeElement; const inputEl = fixture.debugElement.query(By.css('input')).nativeElement;
inputEl.value = 'newValue'; inputEl.value = 'newValue';
@ -396,10 +396,10 @@ export function main() {
inputEl.value = 'newValue'; inputEl.value = 'newValue';
dispatchEvent(inputEl, 'input'); dispatchEvent(inputEl, 'input');
expect(form.get('name').pristine).toBe(false); expect(form.get('name') !.pristine).toBe(false);
form.get('name').valueChanges.subscribe( form.get('name') !.valueChanges.subscribe(
() => { expect(form.get('name').pristine).toBe(true); }); () => { expect(form.get('name') !.pristine).toBe(true); });
dispatchEvent(formEl, 'reset'); dispatchEvent(formEl, 'reset');
})); }));
@ -418,7 +418,7 @@ export function main() {
const form = fixture.debugElement.children[0].injector.get(NgForm); const form = fixture.debugElement.children[0].injector.get(NgForm);
expect(form.value).toEqual({name: {first: '', last: 'Drew'}, email: 'some email'}); expect(form.value).toEqual({name: {first: '', last: 'Drew'}, email: 'some email'});
expect(form.valid).toBe(false); expect(form.valid).toBe(false);
expect(form.control.get('name.first').disabled).toBe(false); expect(form.control.get('name.first') !.disabled).toBe(false);
fixture.componentInstance.isDisabled = true; fixture.componentInstance.isDisabled = true;
fixture.detectChanges(); fixture.detectChanges();
@ -426,7 +426,7 @@ export function main() {
expect(form.value).toEqual({name: {last: 'Drew'}, email: 'some email'}); expect(form.value).toEqual({name: {last: 'Drew'}, email: 'some email'});
expect(form.valid).toBe(true); expect(form.valid).toBe(true);
expect(form.control.get('name.first').disabled).toBe(true); expect(form.control.get('name.first') !.disabled).toBe(true);
})); }));
it('should add disabled attribute in the UI if disable() is called programmatically', it('should add disabled attribute in the UI if disable() is called programmatically',
@ -438,7 +438,7 @@ export function main() {
tick(); tick();
const form = fixture.debugElement.children[0].injector.get(NgForm); const form = fixture.debugElement.children[0].injector.get(NgForm);
form.control.get('name.first').disable(); form.control.get('name.first') !.disable();
fixture.detectChanges(); fixture.detectChanges();
tick(); tick();
@ -455,7 +455,7 @@ export function main() {
fixture.detectChanges(); fixture.detectChanges();
fixture.whenStable().then(() => { fixture.whenStable().then(() => {
const form = fixture.debugElement.children[0].injector.get(NgForm); const form = fixture.debugElement.children[0].injector.get(NgForm);
expect(form.control.get('name').disabled).toBe(true); expect(form.control.get('name') !.disabled).toBe(true);
const customInput = fixture.debugElement.query(By.css('[name="custom"]')); const customInput = fixture.debugElement.query(By.css('[name="custom"]'));
expect(customInput.nativeElement.disabled).toEqual(true); expect(customInput.nativeElement.disabled).toEqual(true);
@ -477,7 +477,7 @@ export function main() {
fixture.detectChanges(); fixture.detectChanges();
tick(); tick();
const form = fixture.debugElement.children[0].injector.get(NgForm); const form = fixture.debugElement.children[0].injector.get(NgForm);
expect(form.control.get('name').disabled).toBe(true); expect(form.control.get('name') !.disabled).toBe(true);
const input = fixture.debugElement.query(By.css('input')); const input = fixture.debugElement.query(By.css('input'));
expect(input.nativeElement.disabled).toEqual(true); expect(input.nativeElement.disabled).toEqual(true);
@ -495,7 +495,7 @@ export function main() {
tick(); tick();
const form = fixture.debugElement.children[0].injector.get(NgForm); const form = fixture.debugElement.children[0].injector.get(NgForm);
form.control.get('food').disable(); form.control.get('food') !.disable();
tick(); tick();
const inputs = fixture.debugElement.queryAll(By.css('input')); const inputs = fixture.debugElement.queryAll(By.css('input'));
@ -620,7 +620,7 @@ export function main() {
fixture.detectChanges(); fixture.detectChanges();
tick(); tick();
fixture.componentInstance.food = null; fixture.componentInstance.food = null !;
fixture.detectChanges(); fixture.detectChanges();
tick(); tick();
@ -632,7 +632,7 @@ export function main() {
fixture.detectChanges(); fixture.detectChanges();
tick(); tick();
fixture.componentInstance.food = undefined; fixture.componentInstance.food = undefined !;
fixture.detectChanges(); fixture.detectChanges();
tick(); tick();
expect(inputs[0].nativeElement.checked).toEqual(false); expect(inputs[0].nativeElement.checked).toEqual(false);
@ -724,7 +724,7 @@ export function main() {
const fixture = initTest(NgModelSelectWithNullForm); const fixture = initTest(NgModelSelectWithNullForm);
const comp = fixture.componentInstance; const comp = fixture.componentInstance;
comp.cities = [{'name': 'SF'}, {'name': 'NYC'}]; comp.cities = [{'name': 'SF'}, {'name': 'NYC'}];
comp.selectedCity = null; comp.selectedCity = null !;
fixture.detectChanges(); fixture.detectChanges();
const select = fixture.debugElement.query(By.css('select')); const select = fixture.debugElement.query(By.css('select'));
@ -745,7 +745,7 @@ export function main() {
it('should throw an error when compareWith is not a function', () => { it('should throw an error when compareWith is not a function', () => {
const fixture = initTest(NgModelSelectWithCustomCompareFnForm); const fixture = initTest(NgModelSelectWithCustomCompareFnForm);
const comp = fixture.componentInstance; const comp = fixture.componentInstance;
comp.compareFn = null; comp.compareFn = null !;
expect(() => fixture.detectChanges()) expect(() => fixture.detectChanges())
.toThrowError(/compareWith must be a function, but received null/); .toThrowError(/compareWith must be a function, but received null/);
}); });
@ -833,7 +833,7 @@ export function main() {
it('should throw an error when compareWith is not a function', () => { it('should throw an error when compareWith is not a function', () => {
const fixture = initTest(NgModelSelectMultipleWithCustomCompareFnForm); const fixture = initTest(NgModelSelectMultipleWithCustomCompareFnForm);
const comp = fixture.componentInstance; const comp = fixture.componentInstance;
comp.compareFn = null; comp.compareFn = null !;
expect(() => fixture.detectChanges()) expect(() => fixture.detectChanges())
.toThrowError(/compareWith must be a function, but received null/); .toThrowError(/compareWith must be a function, but received null/);
}); });
@ -885,7 +885,7 @@ export function main() {
tick(); tick();
const control = const control =
fixture.debugElement.children[0].injector.get(NgForm).control.get('checkbox'); fixture.debugElement.children[0].injector.get(NgForm).control.get('checkbox') !;
const input = fixture.debugElement.query(By.css('input')); const input = fixture.debugElement.query(By.css('input'));
expect(input.nativeElement.checked).toBe(false); expect(input.nativeElement.checked).toBe(false);
@ -921,7 +921,7 @@ export function main() {
tick(); tick();
const control = const control =
fixture.debugElement.children[0].injector.get(NgForm).control.get('email'); fixture.debugElement.children[0].injector.get(NgForm).control.get('email') !;
const input = fixture.debugElement.query(By.css('input')); const input = fixture.debugElement.query(By.css('input'));
expect(control.hasError('email')).toBe(false); expect(control.hasError('email')).toBe(false);
@ -1114,9 +1114,9 @@ export function main() {
.toEqual(pattern.nativeElement.getAttribute('pattern')); .toEqual(pattern.nativeElement.getAttribute('pattern'));
fixture.componentInstance.required = false; fixture.componentInstance.required = false;
fixture.componentInstance.minLen = null; fixture.componentInstance.minLen = null !;
fixture.componentInstance.maxLen = null; fixture.componentInstance.maxLen = null !;
fixture.componentInstance.pattern = null; fixture.componentInstance.pattern = null !;
fixture.detectChanges(); fixture.detectChanges();
expect(form.control.hasError('required', ['required'])).toEqual(false); expect(form.control.hasError('required', ['required'])).toEqual(false);

View File

@ -179,33 +179,33 @@ export function main() {
}); });
it('should not error on "null" pattern', it('should not error on "null" pattern',
() => expect(Validators.pattern(null)(new FormControl('aaAA'))).toBeNull()); () => expect(Validators.pattern(null !)(new FormControl('aaAA'))).toBeNull());
it('should not error on "undefined" pattern', it('should not error on "undefined" pattern',
() => expect(Validators.pattern(undefined)(new FormControl('aaAA'))).toBeNull()); () => expect(Validators.pattern(undefined !)(new FormControl('aaAA'))).toBeNull());
}); });
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); });
it('should collect errors from all the validators', () => { it('should collect errors from all the validators', () => {
const c = Validators.compose([validator('a', true), validator('b', true)]); const c = Validators.compose([validator('a', true), validator('b', true)]) !;
expect(c(new FormControl(''))).toEqual({'a': true, 'b': true}); expect(c(new FormControl(''))).toEqual({'a': true, 'b': true});
}); });
it('should run validators left to right', () => { it('should run validators left to right', () => {
const c = Validators.compose([validator('a', 1), validator('a', 2)]); const c = Validators.compose([validator('a', 1), validator('a', 2)]) !;
expect(c(new FormControl(''))).toEqual({'a': 2}); expect(c(new FormControl(''))).toEqual({'a': 2});
}); });
it('should return null when no errors', () => { it('should return null when no errors', () => {
const c = Validators.compose([Validators.nullValidator, Validators.nullValidator]); const c = Validators.compose([Validators.nullValidator, Validators.nullValidator]) !;
expect(c(new FormControl(''))).toBeNull(); expect(c(new FormControl(''))).toBeNull();
}); });
it('should ignore nulls', () => { it('should ignore nulls', () => {
const c = Validators.compose([null, Validators.required]); const c = Validators.compose([null !, Validators.required]) !;
expect(c(new FormControl(''))).toEqual({'required': true}); expect(c(new FormControl(''))).toEqual({'required': true});
}); });
}); });
@ -221,13 +221,13 @@ export function main() {
} }
it('should return null when given null', it('should return null when given null',
() => { expect(Validators.composeAsync(null)).toBeNull(); }); () => { expect(Validators.composeAsync(null !)).toBeNull(); });
it('should collect errors from all the validators', fakeAsync(() => { it('should collect errors from all the validators', fakeAsync(() => {
const v = Validators.composeAsync( const v = Validators.composeAsync(
[promiseValidator({'one': true}), promiseValidator({'two': true})]); [promiseValidator({'one': true}), promiseValidator({'two': true})]) !;
let errorMap: {[key: string]: any}; let errorMap: {[key: string]: any} = undefined !;
first.call(v(new FormControl('invalid'))) first.call(v(new FormControl('invalid')))
.subscribe((errors: {[key: string]: any}) => errorMap = errors); .subscribe((errors: {[key: string]: any}) => errorMap = errors);
tick(); tick();
@ -236,10 +236,10 @@ export function main() {
})); }));
it('should normalize and evaluate async validator-directives correctly', fakeAsync(() => { it('should normalize and evaluate async validator-directives correctly', fakeAsync(() => {
const v = Validators.composeAsync( const v = Validators.composeAsync([normalizeAsyncValidator(
[normalizeAsyncValidator(new AsyncValidatorDirective('expected', {'one': true}))]); new AsyncValidatorDirective('expected', {'one': true}))]) !;
let errorMap: {[key: string]: any}; let errorMap: {[key: string]: any} = undefined !;
first.call(v(new FormControl('invalid'))) first.call(v(new FormControl('invalid')))
.subscribe((errors: {[key: string]: any}) => errorMap = errors); .subscribe((errors: {[key: string]: any}) => errorMap = errors);
tick(); tick();
@ -248,9 +248,9 @@ export function main() {
})); }));
it('should return null when no errors', fakeAsync(() => { it('should return null when no errors', fakeAsync(() => {
const v = Validators.composeAsync([promiseValidator({'one': true})]); const v = Validators.composeAsync([promiseValidator({'one': true})]) !;
let errorMap: {[key: string]: any}; let errorMap: {[key: string]: any} = undefined !;
first.call(v(new FormControl('expected'))) first.call(v(new FormControl('expected')))
.subscribe((errors: {[key: string]: any}) => errorMap = errors); .subscribe((errors: {[key: string]: any}) => errorMap = errors);
tick(); tick();
@ -259,9 +259,9 @@ export function main() {
})); }));
it('should ignore nulls', fakeAsync(() => { it('should ignore nulls', fakeAsync(() => {
const v = Validators.composeAsync([promiseValidator({'one': true}), null]); const v = Validators.composeAsync([promiseValidator({'one': true}), null !]) !;
let errorMap: {[key: string]: any}; let errorMap: {[key: string]: any} = undefined !;
first.call(v(new FormControl('invalid'))) first.call(v(new FormControl('invalid')))
.subscribe((errors: {[key: string]: any}) => errorMap = errors); .subscribe((errors: {[key: string]: any}) => errorMap = errors);
tick(); tick();
@ -279,13 +279,13 @@ export function main() {
} }
it('should return null when given null', it('should return null when given null',
() => { expect(Validators.composeAsync(null)).toBeNull(); }); () => { expect(Validators.composeAsync(null !)).toBeNull(); });
it('should collect errors from all the validators', () => { it('should collect errors from all the validators', () => {
const v = Validators.composeAsync( const v = Validators.composeAsync(
[observableValidator({'one': true}), observableValidator({'two': true})]); [observableValidator({'one': true}), observableValidator({'two': true})]) !;
let errorMap: {[key: string]: any}; let errorMap: {[key: string]: any} = undefined !;
first.call(v(new FormControl('invalid'))) first.call(v(new FormControl('invalid')))
.subscribe((errors: {[key: string]: any}) => errorMap = errors); .subscribe((errors: {[key: string]: any}) => errorMap = errors);
@ -294,19 +294,19 @@ export function main() {
it('should normalize and evaluate async validator-directives correctly', () => { it('should normalize and evaluate async validator-directives correctly', () => {
const v = Validators.composeAsync( const v = Validators.composeAsync(
[normalizeAsyncValidator(new AsyncValidatorDirective('expected', {'one': true}))]); [normalizeAsyncValidator(new AsyncValidatorDirective('expected', {'one': true}))]) !;
let errorMap: {[key: string]: any}; let errorMap: {[key: string]: any} = undefined !;
first.call(v(new FormControl('invalid'))) first.call(v(new FormControl('invalid')))
.subscribe((errors: {[key: string]: any}) => errorMap = errors); .subscribe((errors: {[key: string]: any}) => errorMap = errors) !;
expect(errorMap).toEqual({'one': true}); expect(errorMap).toEqual({'one': true});
}); });
it('should return null when no errors', () => { it('should return null when no errors', () => {
const v = Validators.composeAsync([observableValidator({'one': true})]); const v = Validators.composeAsync([observableValidator({'one': true})]) !;
let errorMap: {[key: string]: any}; let errorMap: {[key: string]: any} = undefined !;
first.call(v(new FormControl('expected'))) first.call(v(new FormControl('expected')))
.subscribe((errors: {[key: string]: any}) => errorMap = errors); .subscribe((errors: {[key: string]: any}) => errorMap = errors);
@ -314,9 +314,9 @@ export function main() {
}); });
it('should ignore nulls', () => { it('should ignore nulls', () => {
const v = Validators.composeAsync([observableValidator({'one': true}), null]); const v = Validators.composeAsync([observableValidator({'one': true}), null !]) !;
let errorMap: {[key: string]: any}; let errorMap: {[key: string]: any} = undefined !;
first.call(v(new FormControl('invalid'))) first.call(v(new FormControl('invalid')))
.subscribe((errors: {[key: string]: any}) => errorMap = errors); .subscribe((errors: {[key: string]: any}) => errorMap = errors);
@ -329,9 +329,9 @@ export function main() {
} }
const v = Validators.composeAsync( const v = Validators.composeAsync(
[getTimerObs(100, {one: true}), getTimerObs(200, {two: true})]); [getTimerObs(100, {one: true}), getTimerObs(200, {two: true})]) !;
let errorMap: {[key: string]: any}; let errorMap: {[key: string]: any} = undefined !;
first.call(v(new FormControl('invalid'))) first.call(v(new FormControl('invalid')))
.subscribe((errors: {[key: string]: any}) => errorMap = errors); .subscribe((errors: {[key: string]: any}) => errorMap = errors);

View File

@ -4,6 +4,7 @@
"declaration": true, "declaration": true,
"stripInternal": true, "stripInternal": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"strictNullChecks": true,
"module": "es2015", "module": "es2015",
"moduleResolution": "node", "moduleResolution": "node",
"outDir": "../../dist/packages/forms", "outDir": "../../dist/packages/forms",

View File

@ -1,6 +1,6 @@
/** @stable */ /** @stable */
export declare abstract class AbstractControl { export declare abstract class AbstractControl {
asyncValidator: AsyncValidatorFn; asyncValidator: AsyncValidatorFn | null;
readonly dirty: boolean; readonly dirty: boolean;
readonly disabled: boolean; readonly disabled: boolean;
readonly enabled: boolean; readonly enabled: boolean;
@ -15,10 +15,10 @@ export declare abstract class AbstractControl {
readonly touched: boolean; readonly touched: boolean;
readonly untouched: boolean; readonly untouched: boolean;
readonly valid: boolean; readonly valid: boolean;
validator: ValidatorFn; validator: ValidatorFn | null;
readonly value: any; readonly value: any;
readonly valueChanges: Observable<any>; readonly valueChanges: Observable<any>;
constructor(validator: ValidatorFn, asyncValidator: AsyncValidatorFn); constructor(validator: ValidatorFn | null, asyncValidator: AsyncValidatorFn | null);
clearAsyncValidators(): void; clearAsyncValidators(): void;
clearValidators(): void; clearValidators(): void;
disable({onlySelf, emitEvent}?: { disable({onlySelf, emitEvent}?: {
@ -29,7 +29,7 @@ export declare abstract class AbstractControl {
onlySelf?: boolean; onlySelf?: boolean;
emitEvent?: boolean; emitEvent?: boolean;
}): void; }): void;
get(path: Array<string | number> | string): AbstractControl; get(path: Array<string | number> | string): AbstractControl | null;
getError(errorCode: string, path?: string[]): any; getError(errorCode: string, path?: string[]): any;
hasError(errorCode: string, path?: string[]): boolean; hasError(errorCode: string, path?: string[]): boolean;
markAsDirty({onlySelf}?: { markAsDirty({onlySelf}?: {
@ -54,7 +54,7 @@ export declare abstract class AbstractControl {
emitEvent?: boolean; emitEvent?: boolean;
}): void; }): void;
setParent(parent: FormGroup | FormArray): void; setParent(parent: FormGroup | FormArray): void;
setValidators(newValidator: ValidatorFn | ValidatorFn[]): void; setValidators(newValidator: ValidatorFn | ValidatorFn[] | null): void;
abstract setValue(value: any, options?: Object): void; abstract setValue(value: any, options?: Object): void;
updateValueAndValidity({onlySelf, emitEvent}?: { updateValueAndValidity({onlySelf, emitEvent}?: {
onlySelf?: boolean; onlySelf?: boolean;
@ -64,21 +64,21 @@ export declare abstract class AbstractControl {
/** @stable */ /** @stable */
export declare abstract class AbstractControlDirective { export declare abstract class AbstractControlDirective {
readonly control: AbstractControl; readonly abstract control: AbstractControl | null;
readonly dirty: boolean; readonly dirty: boolean | null;
readonly disabled: boolean; readonly disabled: boolean | null;
readonly enabled: boolean; readonly enabled: boolean | null;
readonly errors: ValidationErrors | null; readonly errors: ValidationErrors | null;
readonly invalid: boolean; readonly invalid: boolean | null;
readonly path: string[]; readonly path: string[] | null;
readonly pending: boolean; readonly pending: boolean | null;
readonly pristine: boolean; readonly pristine: boolean | null;
readonly statusChanges: Observable<any>; readonly statusChanges: Observable<any> | null;
readonly touched: boolean; readonly touched: boolean | null;
readonly untouched: boolean; readonly untouched: boolean | null;
readonly valid: boolean; readonly valid: boolean | null;
readonly value: any; readonly value: any;
readonly valueChanges: Observable<any>; readonly valueChanges: Observable<any> | null;
getError(errorCode: string, path?: string[]): any; getError(errorCode: string, path?: string[]): any;
hasError(errorCode: string, path?: string[]): boolean; hasError(errorCode: string, path?: string[]): boolean;
reset(value?: any): void; reset(value?: any): void;
@ -86,11 +86,11 @@ export declare abstract class AbstractControlDirective {
/** @stable */ /** @stable */
export declare class AbstractFormGroupDirective extends ControlContainer implements OnInit, OnDestroy { export declare class AbstractFormGroupDirective extends ControlContainer implements OnInit, OnDestroy {
readonly asyncValidator: AsyncValidatorFn; readonly asyncValidator: AsyncValidatorFn | null;
readonly control: FormGroup; readonly control: FormGroup;
readonly formDirective: Form; readonly formDirective: Form | null;
readonly path: string[]; readonly path: string[];
readonly validator: ValidatorFn; readonly validator: ValidatorFn | null;
ngOnDestroy(): void; ngOnDestroy(): void;
ngOnInit(): void; ngOnInit(): void;
} }
@ -125,10 +125,10 @@ export declare class CheckboxRequiredValidator extends RequiredValidator {
export declare const COMPOSITION_BUFFER_MODE: InjectionToken<boolean>; export declare const COMPOSITION_BUFFER_MODE: InjectionToken<boolean>;
/** @stable */ /** @stable */
export declare class ControlContainer extends AbstractControlDirective { export declare abstract class ControlContainer extends AbstractControlDirective {
readonly formDirective: Form; readonly formDirective: Form | null;
name: string; name: string;
readonly path: string[]; readonly path: string[] | null;
} }
/** @stable */ /** @stable */
@ -175,7 +175,7 @@ export interface Form {
export declare class FormArray extends AbstractControl { export declare class FormArray extends AbstractControl {
controls: AbstractControl[]; controls: AbstractControl[];
readonly length: number; readonly length: number;
constructor(controls: AbstractControl[], validator?: ValidatorFn, asyncValidator?: AsyncValidatorFn); constructor(controls: AbstractControl[], validator?: ValidatorFn | null, asyncValidator?: AsyncValidatorFn | null);
at(index: number): AbstractControl; at(index: number): AbstractControl;
getRawValue(): any[]; getRawValue(): any[];
insert(index: number, control: AbstractControl): void; insert(index: number, control: AbstractControl): void;
@ -198,12 +198,12 @@ export declare class FormArray extends AbstractControl {
/** @stable */ /** @stable */
export declare class FormArrayName extends ControlContainer implements OnInit, OnDestroy { export declare class FormArrayName extends ControlContainer implements OnInit, OnDestroy {
readonly asyncValidator: AsyncValidatorFn; readonly asyncValidator: AsyncValidatorFn | null;
readonly control: FormArray; readonly control: FormArray;
readonly formDirective: FormGroupDirective; readonly formDirective: FormGroupDirective | null;
name: string; name: string;
readonly path: string[]; readonly path: string[];
readonly validator: ValidatorFn; readonly validator: ValidatorFn | null;
constructor(parent: ControlContainer, validators: any[], asyncValidators: any[]); constructor(parent: ControlContainer, validators: any[], asyncValidators: any[]);
ngOnDestroy(): void; ngOnDestroy(): void;
ngOnInit(): void; ngOnInit(): void;
@ -211,18 +211,18 @@ export declare class FormArrayName extends ControlContainer implements OnInit, O
/** @stable */ /** @stable */
export declare class FormBuilder { export declare class FormBuilder {
array(controlsConfig: any[], validator?: ValidatorFn, asyncValidator?: AsyncValidatorFn): FormArray; array(controlsConfig: any[], validator?: ValidatorFn | null, asyncValidator?: AsyncValidatorFn | null): FormArray;
control(formState: Object, validator?: ValidatorFn | ValidatorFn[], asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[]): FormControl; control(formState: Object, validator?: ValidatorFn | ValidatorFn[] | null, asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null): FormControl;
group(controlsConfig: { group(controlsConfig: {
[key: string]: any; [key: string]: any;
}, extra?: { }, extra?: {
[key: string]: any; [key: string]: any;
}): FormGroup; } | null): FormGroup;
} }
/** @stable */ /** @stable */
export declare class FormControl extends AbstractControl { export declare class FormControl extends AbstractControl {
constructor(formState?: any, validator?: ValidatorFn | ValidatorFn[], asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[]); constructor(formState?: any, validator?: ValidatorFn | ValidatorFn[] | null, asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null);
patchValue(value: any, options?: { patchValue(value: any, options?: {
onlySelf?: boolean; onlySelf?: boolean;
emitEvent?: boolean; emitEvent?: boolean;
@ -245,14 +245,14 @@ export declare class FormControl extends AbstractControl {
/** @stable */ /** @stable */
export declare class FormControlDirective extends NgControl implements OnChanges { export declare class FormControlDirective extends NgControl implements OnChanges {
readonly asyncValidator: AsyncValidatorFn; readonly asyncValidator: AsyncValidatorFn | null;
readonly control: FormControl; readonly control: FormControl;
form: FormControl; form: FormControl;
isDisabled: boolean; isDisabled: boolean;
model: any; model: any;
readonly path: string[]; readonly path: string[];
update: EventEmitter<{}>; update: EventEmitter<{}>;
readonly validator: ValidatorFn; readonly validator: ValidatorFn | null;
viewModel: any; viewModel: any;
constructor(validators: Array<Validator | ValidatorFn>, asyncValidators: Array<AsyncValidator | AsyncValidatorFn>, valueAccessors: ControlValueAccessor[]); constructor(validators: Array<Validator | ValidatorFn>, asyncValidators: Array<AsyncValidator | AsyncValidatorFn>, valueAccessors: ControlValueAccessor[]);
ngOnChanges(changes: SimpleChanges): void; ngOnChanges(changes: SimpleChanges): void;
@ -269,7 +269,7 @@ export declare class FormControlName extends NgControl implements OnChanges, OnD
name: string; name: string;
readonly path: string[]; readonly path: string[];
update: EventEmitter<{}>; update: EventEmitter<{}>;
readonly validator: ValidatorFn; readonly validator: ValidatorFn | null;
constructor(parent: ControlContainer, validators: Array<Validator | ValidatorFn>, asyncValidators: Array<AsyncValidator | AsyncValidatorFn>, valueAccessors: ControlValueAccessor[]); constructor(parent: ControlContainer, validators: Array<Validator | ValidatorFn>, asyncValidators: Array<AsyncValidator | AsyncValidatorFn>, valueAccessors: ControlValueAccessor[]);
ngOnChanges(changes: SimpleChanges): void; ngOnChanges(changes: SimpleChanges): void;
ngOnDestroy(): void; ngOnDestroy(): void;
@ -283,7 +283,7 @@ export declare class FormGroup extends AbstractControl {
}; };
constructor(controls: { constructor(controls: {
[key: string]: AbstractControl; [key: string]: AbstractControl;
}, validator?: ValidatorFn, asyncValidator?: AsyncValidatorFn); }, validator?: ValidatorFn | null, asyncValidator?: AsyncValidatorFn | null);
addControl(name: string, control: AbstractControl): void; addControl(name: string, control: AbstractControl): void;
contains(controlName: string): boolean; contains(controlName: string): boolean;
getRawValue(): any; getRawValue(): any;
@ -371,10 +371,10 @@ export declare const NG_VALUE_ACCESSOR: InjectionToken<ControlValueAccessor>;
/** @stable */ /** @stable */
export declare abstract class NgControl extends AbstractControlDirective { export declare abstract class NgControl extends AbstractControlDirective {
readonly asyncValidator: AsyncValidatorFn; readonly asyncValidator: AsyncValidatorFn | null;
name: string; name: string | null;
readonly validator: ValidatorFn; readonly validator: ValidatorFn | null;
valueAccessor: ControlValueAccessor; valueAccessor: ControlValueAccessor | null;
abstract viewToModelUpdate(newValue: any): void; abstract viewToModelUpdate(newValue: any): void;
} }
@ -417,7 +417,7 @@ export declare class NgForm extends ControlContainer implements Form {
/** @stable */ /** @stable */
export declare class NgModel extends NgControl implements OnChanges, OnDestroy { export declare class NgModel extends NgControl implements OnChanges, OnDestroy {
readonly asyncValidator: AsyncValidatorFn; readonly asyncValidator: AsyncValidatorFn | null;
readonly control: FormControl; readonly control: FormControl;
readonly formDirective: any; readonly formDirective: any;
isDisabled: boolean; isDisabled: boolean;
@ -429,7 +429,7 @@ export declare class NgModel extends NgControl implements OnChanges, OnDestroy {
}; };
readonly path: string[]; readonly path: string[];
update: EventEmitter<{}>; update: EventEmitter<{}>;
readonly validator: ValidatorFn; readonly validator: ValidatorFn | null;
viewModel: any; viewModel: any;
constructor(parent: ControlContainer, validators: Array<Validator | ValidatorFn>, asyncValidators: Array<AsyncValidator | AsyncValidatorFn>, valueAccessors: ControlValueAccessor[]); constructor(parent: ControlContainer, validators: Array<Validator | ValidatorFn>, asyncValidators: Array<AsyncValidator | AsyncValidatorFn>, valueAccessors: ControlValueAccessor[]);
ngOnChanges(changes: SimpleChanges): void; ngOnChanges(changes: SimpleChanges): void;
@ -532,8 +532,9 @@ export interface ValidatorFn {
/** @stable */ /** @stable */
export declare class Validators { export declare class Validators {
static compose(validators: ValidatorFn[]): ValidatorFn; static compose(validators: null): null;
static composeAsync(validators: AsyncValidatorFn[]): AsyncValidatorFn; static compose(validators: (ValidatorFn | null | undefined)[]): ValidatorFn | null;
static composeAsync(validators: (AsyncValidatorFn | null)[]): AsyncValidatorFn | null;
static email(control: AbstractControl): ValidationErrors | null; static email(control: AbstractControl): ValidationErrors | null;
static maxLength(maxLength: number): ValidatorFn; static maxLength(maxLength: number): ValidatorFn;
static minLength(minLength: number): ValidatorFn; static minLength(minLength: number): ValidatorFn;