style(lint): re-format modules/@angular

This commit is contained in:
Alex Eagle 2016-06-08 16:38:52 -07:00
parent bbed364e7b
commit f39c9c9e75
589 changed files with 21829 additions and 24259 deletions

View File

@ -9,7 +9,7 @@ require('./tools/check-environment')(
const gulp = require('gulp'); const gulp = require('gulp');
const path = require('path'); const path = require('path');
const srcsToFmt = ['tools/**/*.ts']; const srcsToFmt = ['tools/**/*.ts', 'modules/@angular/**/*.ts'];
gulp.task('format:enforce', () => { gulp.task('format:enforce', () => {
const format = require('gulp-clang-format'); const format = require('gulp-clang-format');

View File

@ -1,6 +1,8 @@
import {Type} from '@angular/core'; import {Type} from '@angular/core';
import {FORM_DIRECTIVES} from './forms-deprecated';
import {CORE_DIRECTIVES} from './directives'; import {CORE_DIRECTIVES} from './directives';
import {FORM_DIRECTIVES} from './forms-deprecated';
/** /**
* A collection of Angular core directives that are likely to be used in each and every Angular * A collection of Angular core directives that are likely to be used in each and every Angular

View File

@ -3,11 +3,11 @@
* @description * @description
* Common directives shipped with Angular. * Common directives shipped with Angular.
*/ */
export {CORE_DIRECTIVES} from './directives/core_directives';
export {NgClass} from './directives/ng_class'; export {NgClass} from './directives/ng_class';
export {NgFor} from './directives/ng_for'; export {NgFor} from './directives/ng_for';
export {NgIf} from './directives/ng_if'; export {NgIf} from './directives/ng_if';
export {NgTemplateOutlet} from './directives/ng_template_outlet'; export {NgLocalization, NgPlural, NgPluralCase} from './directives/ng_plural';
export {NgStyle} from './directives/ng_style'; export {NgStyle} from './directives/ng_style';
export {NgSwitch, NgSwitchWhen, NgSwitchDefault} from './directives/ng_switch'; export {NgSwitch, NgSwitchDefault, NgSwitchWhen} from './directives/ng_switch';
export {NgPlural, NgPluralCase, NgLocalization} from './directives/ng_plural'; export {NgTemplateOutlet} from './directives/ng_template_outlet';
export {CORE_DIRECTIVES} from './directives/core_directives';

View File

@ -1,11 +1,13 @@
import {Type} from '../facade/lang'; import {Type} from '../facade/lang';
import {NgClass} from './ng_class'; import {NgClass} from './ng_class';
import {NgFor} from './ng_for'; import {NgFor} from './ng_for';
import {NgIf} from './ng_if'; import {NgIf} from './ng_if';
import {NgTemplateOutlet} from './ng_template_outlet';
import {NgStyle} from './ng_style';
import {NgSwitch, NgSwitchWhen, NgSwitchDefault} from './ng_switch';
import {NgPlural, NgPluralCase} from './ng_plural'; import {NgPlural, NgPluralCase} from './ng_plural';
import {NgStyle} from './ng_style';
import {NgSwitch, NgSwitchDefault, NgSwitchWhen} from './ng_switch';
import {NgTemplateOutlet} from './ng_template_outlet';
/** /**
* A collection of Angular core directives that are likely to be used in each and every Angular * A collection of Angular core directives that are likely to be used in each and every Angular
@ -59,5 +61,5 @@ export const CORE_DIRECTIVES: Type[] = /*@ts2dart_const*/[
NgSwitchWhen, NgSwitchWhen,
NgSwitchDefault, NgSwitchDefault,
NgPlural, NgPlural,
NgPluralCase NgPluralCase,
]; ];

View File

@ -1,18 +1,8 @@
import { import {CollectionChangeRecord, Directive, DoCheck, ElementRef, IterableDiffer, IterableDiffers, KeyValueChangeRecord, KeyValueDiffer, KeyValueDiffers, OnDestroy, Renderer} from '@angular/core';
DoCheck,
OnDestroy,
Directive,
ElementRef,
IterableDiffers,
KeyValueDiffers,
Renderer,
IterableDiffer,
KeyValueDiffer,
CollectionChangeRecord,
KeyValueChangeRecord
} from '@angular/core';
import {isPresent, isString, isArray} from '../facade/lang';
import {StringMapWrapper, isListLikeIterable} from '../facade/collection'; import {StringMapWrapper, isListLikeIterable} from '../facade/collection';
import {isArray, isPresent, isString} from '../facade/lang';
/** /**
* The `NgClass` directive conditionally adds and removes CSS classes on an HTML element based on * The `NgClass` directive conditionally adds and removes CSS classes on an HTML element based on
@ -80,10 +70,11 @@ export class NgClass implements DoCheck, OnDestroy {
private _iterableDiffer: IterableDiffer; private _iterableDiffer: IterableDiffer;
private _keyValueDiffer: KeyValueDiffer; private _keyValueDiffer: KeyValueDiffer;
private _initialClasses: string[] = []; private _initialClasses: string[] = [];
private _rawClass: string[] | Set<string>; private _rawClass: string[]|Set<string>;
constructor(private _iterableDiffers: IterableDiffers, private _keyValueDiffers: KeyValueDiffers, constructor(
private _ngEl: ElementRef, private _renderer: Renderer) {} private _iterableDiffers: IterableDiffers, private _keyValueDiffers: KeyValueDiffers,
private _ngEl: ElementRef, private _renderer: Renderer) {}
set initialClasses(v: string) { set initialClasses(v: string) {
this._applyInitialClasses(true); this._applyInitialClasses(true);
@ -92,14 +83,14 @@ export class NgClass implements DoCheck, OnDestroy {
this._applyClasses(this._rawClass, false); this._applyClasses(this._rawClass, false);
} }
set rawClass(v: string | string[] | Set<string>| {[key: string]: any}) { set rawClass(v: string|string[]|Set<string>|{[key: string]: any}) {
this._cleanupClasses(this._rawClass); this._cleanupClasses(this._rawClass);
if (isString(v)) { if (isString(v)) {
v = (<string>v).split(' '); v = (<string>v).split(' ');
} }
this._rawClass = <string[] | Set<string>>v; this._rawClass = <string[]|Set<string>>v;
this._iterableDiffer = null; this._iterableDiffer = null;
this._keyValueDiffer = null; this._keyValueDiffer = null;
if (isPresent(v)) { if (isPresent(v)) {
@ -128,7 +119,7 @@ export class NgClass implements DoCheck, OnDestroy {
ngOnDestroy(): void { this._cleanupClasses(this._rawClass); } ngOnDestroy(): void { this._cleanupClasses(this._rawClass); }
private _cleanupClasses(rawClassVal: string[] | Set<string>| {[key: string]: any}): void { private _cleanupClasses(rawClassVal: string[]|Set<string>|{[key: string]: any}): void {
this._applyClasses(rawClassVal, true); this._applyClasses(rawClassVal, true);
this._applyInitialClasses(false); this._applyInitialClasses(false);
} }
@ -156,18 +147,18 @@ export class NgClass implements DoCheck, OnDestroy {
this._initialClasses.forEach(className => this._toggleClass(className, !isCleanup)); this._initialClasses.forEach(className => this._toggleClass(className, !isCleanup));
} }
private _applyClasses(rawClassVal: string[] | Set<string>| {[key: string]: any}, private _applyClasses(
isCleanup: boolean) { rawClassVal: string[]|Set<string>|{[key: string]: any}, isCleanup: boolean) {
if (isPresent(rawClassVal)) { if (isPresent(rawClassVal)) {
if (isArray(rawClassVal)) { if (isArray(rawClassVal)) {
(<string[]>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup)); (<string[]>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup));
} else if (rawClassVal instanceof Set) { } else if (rawClassVal instanceof Set) {
(<Set<string>>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup)); (<Set<string>>rawClassVal).forEach(className => this._toggleClass(className, !isCleanup));
} else { } else {
StringMapWrapper.forEach(<{[k: string]: any}>rawClassVal, StringMapWrapper.forEach(
(expVal: any, className: string) => { <{[k: string]: any}>rawClassVal, (expVal: any, className: string) => {
if (isPresent(expVal)) this._toggleClass(className, !isCleanup); if (isPresent(expVal)) this._toggleClass(className, !isCleanup);
}); });
} }
} }
} }

View File

@ -1,18 +1,7 @@
import { import {ChangeDetectorRef, CollectionChangeRecord, DefaultIterableDiffer, Directive, DoCheck, EmbeddedViewRef, IterableDiffer, IterableDiffers, TemplateRef, TrackByFn, ViewContainerRef} from '@angular/core';
DoCheck,
Directive,
ChangeDetectorRef,
IterableDiffer,
IterableDiffers,
ViewContainerRef,
TemplateRef,
EmbeddedViewRef,
TrackByFn,
DefaultIterableDiffer,
CollectionChangeRecord
} from '@angular/core';
import {isPresent, isBlank, getTypeNameForDebugging} from '../facade/lang';
import {BaseException} from '../facade/exceptions'; import {BaseException} from '../facade/exceptions';
import {getTypeNameForDebugging, isBlank, isPresent} from '../facade/lang';
export class NgForRow { export class NgForRow {
constructor(public $implicit: any, public index: number, public count: number) {} constructor(public $implicit: any, public index: number, public count: number) {}
@ -87,8 +76,9 @@ export class NgFor implements DoCheck {
_ngForTrackBy: TrackByFn; _ngForTrackBy: TrackByFn;
private _differ: IterableDiffer; private _differ: IterableDiffer;
constructor(private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef<NgForRow>, constructor(
private _iterableDiffers: IterableDiffers, private _cdr: ChangeDetectorRef) {} private _viewContainer: ViewContainerRef, private _templateRef: TemplateRef<NgForRow>,
private _iterableDiffers: IterableDiffers, private _cdr: ChangeDetectorRef) {}
set ngForOf(value: any) { set ngForOf(value: any) {
this._ngForOf = value; this._ngForOf = value;
@ -121,16 +111,19 @@ export class NgFor implements DoCheck {
// TODO(rado): check if change detection can produce a change record that is // TODO(rado): check if change detection can produce a change record that is
// easier to consume than current. // easier to consume than current.
var recordViewTuples: RecordViewTuple[] = []; var recordViewTuples: RecordViewTuple[] = [];
changes.forEachRemovedItem((removedRecord: CollectionChangeRecord) => changes.forEachRemovedItem(
recordViewTuples.push(new RecordViewTuple(removedRecord, null))); (removedRecord: CollectionChangeRecord) =>
recordViewTuples.push(new RecordViewTuple(removedRecord, null)));
changes.forEachMovedItem((movedRecord: CollectionChangeRecord) => changes.forEachMovedItem(
recordViewTuples.push(new RecordViewTuple(movedRecord, null))); (movedRecord: CollectionChangeRecord) =>
recordViewTuples.push(new RecordViewTuple(movedRecord, null)));
var insertTuples = this._bulkRemove(recordViewTuples); var insertTuples = this._bulkRemove(recordViewTuples);
changes.forEachAddedItem((addedRecord: CollectionChangeRecord) => changes.forEachAddedItem(
insertTuples.push(new RecordViewTuple(addedRecord, null))); (addedRecord: CollectionChangeRecord) =>
insertTuples.push(new RecordViewTuple(addedRecord, null)));
this._bulkInsert(insertTuples); this._bulkInsert(insertTuples);
@ -155,8 +148,9 @@ export class NgFor implements DoCheck {
} }
private _bulkRemove(tuples: RecordViewTuple[]): RecordViewTuple[] { private _bulkRemove(tuples: RecordViewTuple[]): RecordViewTuple[] {
tuples.sort((a: RecordViewTuple, b: RecordViewTuple) => tuples.sort(
a.record.previousIndex - b.record.previousIndex); (a: RecordViewTuple, b: RecordViewTuple) =>
a.record.previousIndex - b.record.previousIndex);
var movedTuples: RecordViewTuple[] = []; var movedTuples: RecordViewTuple[] = [];
for (var i = tuples.length - 1; i >= 0; i--) { for (var i = tuples.length - 1; i >= 0; i--) {
var tuple = tuples[i]; var tuple = tuples[i];

View File

@ -1,6 +1,8 @@
import {Directive, ViewContainerRef, TemplateRef} from '@angular/core'; import {Directive, TemplateRef, ViewContainerRef} from '@angular/core';
import {isBlank} from '../facade/lang'; import {isBlank} from '../facade/lang';
/** /**
* Removes or recreates a portion of the DOM tree based on an {expression}. * Removes or recreates a portion of the DOM tree based on an {expression}.
* *

View File

@ -1,15 +1,7 @@
import { import {AfterContentInit, Attribute, ContentChildren, Directive, Input, QueryList, TemplateRef, ViewContainerRef} from '@angular/core';
Directive,
ViewContainerRef,
TemplateRef,
ContentChildren,
QueryList,
Attribute,
AfterContentInit,
Input
} from '@angular/core';
import {isPresent, NumberWrapper} from '../facade/lang';
import {Map} from '../facade/collection'; import {Map} from '../facade/collection';
import {NumberWrapper, isPresent} from '../facade/lang';
import {SwitchView} from './ng_switch'; import {SwitchView} from './ng_switch';
@ -81,8 +73,9 @@ export abstract class NgLocalization { abstract getPluralCategory(value: any): s
export class NgPluralCase { export class NgPluralCase {
/** @internal */ /** @internal */
_view: SwitchView; _view: SwitchView;
constructor(@Attribute('ngPluralCase') public value: string, template: TemplateRef<Object>, constructor(
viewContainer: ViewContainerRef) { @Attribute('ngPluralCase') public value: string, template: TemplateRef<Object>,
viewContainer: ViewContainerRef) {
this._view = new SwitchView(viewContainer, template); this._view = new SwitchView(viewContainer, template);
} }
} }
@ -143,7 +136,7 @@ export class NgPlural implements AfterContentInit {
} }
/** @internal */ /** @internal */
_isValueView(pluralCase: NgPluralCase): boolean { return pluralCase.value[0] === "="; } _isValueView(pluralCase: NgPluralCase): boolean { return pluralCase.value[0] === '='; }
/** @internal */ /** @internal */
_formatValue(pluralCase: NgPluralCase): any { _formatValue(pluralCase: NgPluralCase): any {

View File

@ -1,13 +1,7 @@
import { import {Directive, DoCheck, ElementRef, KeyValueChangeRecord, KeyValueDiffer, KeyValueDiffers, Renderer} from '@angular/core';
DoCheck,
KeyValueChangeRecord, import {isBlank, isPresent} from '../facade/lang';
KeyValueDiffer,
KeyValueDiffers,
ElementRef,
Directive,
Renderer
} from '@angular/core';
import {isPresent, isBlank} from '../facade/lang';
/** /**
* The `NgStyle` directive changes styles based on a result of expression evaluation. * The `NgStyle` directive changes styles based on a result of expression evaluation.
@ -69,8 +63,8 @@ export class NgStyle implements DoCheck {
/** @internal */ /** @internal */
_differ: KeyValueDiffer; _differ: KeyValueDiffer;
constructor(private _differs: KeyValueDiffers, private _ngEl: ElementRef, constructor(
private _renderer: Renderer) {} private _differs: KeyValueDiffers, private _ngEl: ElementRef, private _renderer: Renderer) {}
set rawStyle(v: {[key: string]: string}) { set rawStyle(v: {[key: string]: string}) {
this._rawStyle = v; this._rawStyle = v;

View File

@ -1,12 +1,13 @@
import {Directive, Host, ViewContainerRef, TemplateRef} from '@angular/core'; import {Directive, Host, TemplateRef, ViewContainerRef} from '@angular/core';
import {isPresent, isBlank, normalizeBlank} from '../facade/lang';
import {ListWrapper, Map} from '../facade/collection'; import {ListWrapper, Map} from '../facade/collection';
import {isBlank, isPresent, normalizeBlank} from '../facade/lang';
const _WHEN_DEFAULT = /*@ts2dart_const*/ new Object(); const _WHEN_DEFAULT = /*@ts2dart_const*/ new Object();
export class SwitchView { export class SwitchView {
constructor(private _viewContainerRef: ViewContainerRef, constructor(
private _templateRef: TemplateRef<Object>) {} private _viewContainerRef: ViewContainerRef, private _templateRef: TemplateRef<Object>) {}
create(): void { this._viewContainerRef.createEmbeddedView(this._templateRef); } create(): void { this._viewContainerRef.createEmbeddedView(this._templateRef); }
@ -180,8 +181,9 @@ export class NgSwitchWhen {
_view: SwitchView; _view: SwitchView;
private _switch: NgSwitch; private _switch: NgSwitch;
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>, constructor(
@Host() ngSwitch: NgSwitch) { viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>,
@Host() ngSwitch: NgSwitch) {
this._switch = ngSwitch; this._switch = ngSwitch;
this._view = new SwitchView(viewContainer, templateRef); this._view = new SwitchView(viewContainer, templateRef);
} }
@ -202,8 +204,9 @@ export class NgSwitchWhen {
*/ */
@Directive({selector: '[ngSwitchDefault]'}) @Directive({selector: '[ngSwitchDefault]'})
export class NgSwitchDefault { export class NgSwitchDefault {
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>, constructor(
@Host() sswitch: NgSwitch) { viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>,
@Host() sswitch: NgSwitch) {
sswitch._registerView(_WHEN_DEFAULT, new SwitchView(viewContainer, templateRef)); sswitch._registerView(_WHEN_DEFAULT, new SwitchView(viewContainer, templateRef));
} }
} }

View File

@ -1,6 +1,8 @@
import {Directive, Input, ViewContainerRef, ViewRef, TemplateRef} from '@angular/core'; import {Directive, Input, TemplateRef, ViewContainerRef, ViewRef} from '@angular/core';
import {isPresent} from '../facade/lang'; import {isPresent} from '../facade/lang';
/** /**
* Creates and inserts an embedded view based on a prepared `TemplateRef`. * Creates and inserts an embedded view based on a prepared `TemplateRef`.
* *

View File

@ -10,39 +10,32 @@
* Forms providers are not included in default providers; you must import these providers * Forms providers are not included in default providers; you must import these providers
* explicitly. * explicitly.
*/ */
export {AbstractControl, Control, ControlGroup, ControlArray} from './forms-deprecated/model'; import {Type} from '@angular/core';
import {RadioControlRegistry} from './forms-deprecated/directives/radio_control_value_accessor';
import {FormBuilder} from './forms-deprecated/form_builder';
export {FORM_DIRECTIVES, RadioButtonState} from './forms-deprecated/directives';
export {AbstractControlDirective} from './forms-deprecated/directives/abstract_control_directive'; export {AbstractControlDirective} from './forms-deprecated/directives/abstract_control_directive';
export {Form} from './forms-deprecated/directives/form_interface'; export {CheckboxControlValueAccessor} from './forms-deprecated/directives/checkbox_value_accessor';
export {ControlContainer} from './forms-deprecated/directives/control_container'; export {ControlContainer} from './forms-deprecated/directives/control_container';
export {NgControlName} from './forms-deprecated/directives/ng_control_name';
export {NgFormControl} from './forms-deprecated/directives/ng_form_control';
export {NgModel} from './forms-deprecated/directives/ng_model';
export {NgControl} from './forms-deprecated/directives/ng_control';
export {NgControlGroup} from './forms-deprecated/directives/ng_control_group';
export {NgFormModel} from './forms-deprecated/directives/ng_form_model';
export {NgForm} from './forms-deprecated/directives/ng_form';
export {ControlValueAccessor, NG_VALUE_ACCESSOR} from './forms-deprecated/directives/control_value_accessor'; export {ControlValueAccessor, NG_VALUE_ACCESSOR} from './forms-deprecated/directives/control_value_accessor';
export {DefaultValueAccessor} from './forms-deprecated/directives/default_value_accessor'; export {DefaultValueAccessor} from './forms-deprecated/directives/default_value_accessor';
export {Form} from './forms-deprecated/directives/form_interface';
export {NgControl} from './forms-deprecated/directives/ng_control';
export {NgControlGroup} from './forms-deprecated/directives/ng_control_group';
export {NgControlName} from './forms-deprecated/directives/ng_control_name';
export {NgControlStatus} from './forms-deprecated/directives/ng_control_status'; export {NgControlStatus} from './forms-deprecated/directives/ng_control_status';
export {CheckboxControlValueAccessor} from './forms-deprecated/directives/checkbox_value_accessor'; export {NgForm} from './forms-deprecated/directives/ng_form';
export { export {NgFormControl} from './forms-deprecated/directives/ng_form_control';
NgSelectOption, export {NgFormModel} from './forms-deprecated/directives/ng_form_model';
SelectControlValueAccessor export {NgModel} from './forms-deprecated/directives/ng_model';
} from './forms-deprecated/directives/select_control_value_accessor'; export {NgSelectOption, SelectControlValueAccessor} from './forms-deprecated/directives/select_control_value_accessor';
export {FORM_DIRECTIVES, RadioButtonState} from './forms-deprecated/directives'; export {MaxLengthValidator, MinLengthValidator, PatternValidator, RequiredValidator, Validator} from './forms-deprecated/directives/validators';
export {NG_VALIDATORS, NG_ASYNC_VALIDATORS, Validators} from './forms-deprecated/validators';
export {
RequiredValidator,
MinLengthValidator,
MaxLengthValidator,
PatternValidator,
Validator
} from './forms-deprecated/directives/validators';
export {FormBuilder} from './forms-deprecated/form_builder'; export {FormBuilder} from './forms-deprecated/form_builder';
import {FormBuilder} from './forms-deprecated/form_builder'; export {AbstractControl, Control, ControlArray, ControlGroup} from './forms-deprecated/model';
import {RadioControlRegistry} from './forms-deprecated/directives/radio_control_value_accessor'; export {NG_ASYNC_VALIDATORS, NG_VALIDATORS, Validators} from './forms-deprecated/validators';
import {Type} from '@angular/core';
/** /**
* Shorthand set of providers used for building Angular forms. * Shorthand set of providers used for building Angular forms.

View File

@ -1,60 +1,37 @@
import {Type} from '@angular/core'; import {Type} from '@angular/core';
import {NgControlName} from './directives/ng_control_name';
import {NgFormControl} from './directives/ng_form_control';
import {NgModel} from './directives/ng_model';
import {NgControlGroup} from './directives/ng_control_group';
import {NgFormModel} from './directives/ng_form_model';
import {NgForm} from './directives/ng_form';
import {DefaultValueAccessor} from './directives/default_value_accessor';
import {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor'; import {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
import {DefaultValueAccessor} from './directives/default_value_accessor';
import {NgControlGroup} from './directives/ng_control_group';
import {NgControlName} from './directives/ng_control_name';
import {NgControlStatus} from './directives/ng_control_status';
import {NgForm} from './directives/ng_form';
import {NgFormControl} from './directives/ng_form_control';
import {NgFormModel} from './directives/ng_form_model';
import {NgModel} from './directives/ng_model';
import {NumberValueAccessor} from './directives/number_value_accessor'; import {NumberValueAccessor} from './directives/number_value_accessor';
import {RadioControlValueAccessor} from './directives/radio_control_value_accessor'; import {RadioControlValueAccessor} from './directives/radio_control_value_accessor';
import {NgControlStatus} from './directives/ng_control_status'; import {NgSelectOption, SelectControlValueAccessor} from './directives/select_control_value_accessor';
import { import {NgSelectMultipleOption, SelectMultipleControlValueAccessor} from './directives/select_multiple_control_value_accessor';
SelectControlValueAccessor, import {MaxLengthValidator, MinLengthValidator, PatternValidator, RequiredValidator} from './directives/validators';
NgSelectOption
} from './directives/select_control_value_accessor';
import {
SelectMultipleControlValueAccessor,
NgSelectMultipleOption
} from './directives/select_multiple_control_value_accessor';
import {
RequiredValidator,
MinLengthValidator,
MaxLengthValidator,
PatternValidator
} from './directives/validators';
export {NgControlName} from './directives/ng_control_name';
export {NgFormControl} from './directives/ng_form_control';
export {NgModel} from './directives/ng_model';
export {NgControlGroup} from './directives/ng_control_group';
export {NgFormModel} from './directives/ng_form_model';
export {NgForm} from './directives/ng_form';
export {DefaultValueAccessor} from './directives/default_value_accessor';
export {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor'; export {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
export {
RadioControlValueAccessor,
RadioButtonState
} from './directives/radio_control_value_accessor';
export {NumberValueAccessor} from './directives/number_value_accessor';
export {NgControlStatus} from './directives/ng_control_status';
export {
SelectControlValueAccessor,
NgSelectOption
} from './directives/select_control_value_accessor';
export {
SelectMultipleControlValueAccessor,
NgSelectMultipleOption
} from './directives/select_multiple_control_value_accessor';
export {
RequiredValidator,
MinLengthValidator,
MaxLengthValidator,
PatternValidator
} from './directives/validators';
export {NgControl} from './directives/ng_control';
export {ControlValueAccessor} from './directives/control_value_accessor'; export {ControlValueAccessor} from './directives/control_value_accessor';
export {DefaultValueAccessor} from './directives/default_value_accessor';
export {NgControl} from './directives/ng_control';
export {NgControlGroup} from './directives/ng_control_group';
export {NgControlName} from './directives/ng_control_name';
export {NgControlStatus} from './directives/ng_control_status';
export {NgForm} from './directives/ng_form';
export {NgFormControl} from './directives/ng_form_control';
export {NgFormModel} from './directives/ng_form_model';
export {NgModel} from './directives/ng_model';
export {NumberValueAccessor} from './directives/number_value_accessor';
export {RadioButtonState, RadioControlValueAccessor} from './directives/radio_control_value_accessor';
export {NgSelectOption, SelectControlValueAccessor} from './directives/select_control_value_accessor';
export {NgSelectMultipleOption, SelectMultipleControlValueAccessor} from './directives/select_multiple_control_value_accessor';
export {MaxLengthValidator, MinLengthValidator, PatternValidator, RequiredValidator} from './directives/validators';
/** /**
* *
@ -95,5 +72,5 @@ export const FORM_DIRECTIVES: Type[] = /*@ts2dart_const*/[
RequiredValidator, RequiredValidator,
MinLengthValidator, MinLengthValidator,
MaxLengthValidator, MaxLengthValidator,
PatternValidator PatternValidator,
]; ];

View File

@ -1,6 +1,7 @@
import {AbstractControl} from '../model';
import {isPresent} from '../../facade/lang';
import {unimplemented} from '../../facade/exceptions'; import {unimplemented} from '../../facade/exceptions';
import {isPresent} from '../../facade/lang';
import {AbstractControl} from '../model';
/** /**
* Base class for control directives. * Base class for control directives.

View File

@ -1,5 +1,6 @@
import {Directive, Renderer, ElementRef, forwardRef} from '@angular/core'; import {Directive, ElementRef, Renderer, forwardRef} from '@angular/core';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from './control_value_accessor';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
export const CHECKBOX_VALUE_ACCESSOR: any = /*@ts2dart_const*/ { export const CHECKBOX_VALUE_ACCESSOR: any = /*@ts2dart_const*/ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

View File

@ -1,5 +1,6 @@
import {Form} from './form_interface';
import {AbstractControlDirective} from './abstract_control_directive'; import {AbstractControlDirective} from './abstract_control_directive';
import {Form} from './form_interface';
/** /**
* A directive that contains multiple {@link NgControl}s. * A directive that contains multiple {@link NgControl}s.

View File

@ -34,4 +34,4 @@ export interface ControlValueAccessor {
* @experimental * @experimental
*/ */
export const NG_VALUE_ACCESSOR: OpaqueToken = export const NG_VALUE_ACCESSOR: OpaqueToken =
/*@ts2dart_const*/ new OpaqueToken("NgValueAccessor"); /*@ts2dart_const*/ new OpaqueToken('NgValueAccessor');

View File

@ -1,6 +1,8 @@
import {Directive, ElementRef, Renderer, forwardRef} from '@angular/core'; import {Directive, ElementRef, Renderer, forwardRef} from '@angular/core';
import {isBlank} from '../../facade/lang'; import {isBlank} from '../../facade/lang';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from './control_value_accessor';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
export const DEFAULT_VALUE_ACCESSOR: any = /*@ts2dart_const*/ export const DEFAULT_VALUE_ACCESSOR: any = /*@ts2dart_const*/
/* @ts2dart_Provider */ { /* @ts2dart_Provider */ {

View File

@ -1,6 +1,8 @@
import {Control, ControlGroup} from '../model';
import {NgControl} from './ng_control'; import {NgControl} from './ng_control';
import {NgControlGroup} from './ng_control_group'; import {NgControlGroup} from './ng_control_group';
import {Control, ControlGroup} from '../model';
/** /**
* An interface that {@link NgFormModel} and {@link NgForm} implement. * An interface that {@link NgFormModel} and {@link NgForm} implement.

View File

@ -1,9 +1,10 @@
import {unimplemented} from '../../facade/exceptions'; import {unimplemented} from '../../facade/exceptions';
import {ControlValueAccessor} from './control_value_accessor';
import {AbstractControlDirective} from './abstract_control_directive'; import {AbstractControlDirective} from './abstract_control_directive';
import {ControlValueAccessor} from './control_value_accessor';
import {AsyncValidatorFn, ValidatorFn} from './validators'; import {AsyncValidatorFn, ValidatorFn} from './validators';
/** /**
* A base class that all control directive extend. * A base class that all control directive extend.
* It binds a {@link Control} object to a DOM element. * It binds a {@link Control} object to a DOM element.

View File

@ -1,19 +1,11 @@
import { import {Directive, Host, Inject, OnDestroy, OnInit, Optional, Self, SkipSelf, forwardRef} from '@angular/core';
OnInit,
OnDestroy,
Directive,
Optional,
Inject,
Host,
SkipSelf,
forwardRef,
Self
} from '@angular/core';
import {ControlContainer} from './control_container';
import {controlPath, composeValidators, composeAsyncValidators} from './shared';
import {ControlGroup} from '../model'; import {ControlGroup} from '../model';
import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';
import {ControlContainer} from './control_container';
import {Form} from './form_interface'; import {Form} from './form_interface';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {composeAsyncValidators, composeValidators, controlPath} from './shared';
import {AsyncValidatorFn, ValidatorFn} from './validators'; import {AsyncValidatorFn, ValidatorFn} from './validators';
export const controlGroupProvider: any = export const controlGroupProvider: any =
@ -79,9 +71,10 @@ export class NgControlGroup extends ControlContainer implements OnInit,
/** @internal */ /** @internal */
_parent: ControlContainer; _parent: ControlContainer;
constructor(@Host() @SkipSelf() parent: ControlContainer, constructor(
@Optional() @Self() @Inject(NG_VALIDATORS) private _validators: any[], @Host() @SkipSelf() parent: ControlContainer,
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[]) { @Optional() @Self() @Inject(NG_VALIDATORS) private _validators: any[],
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[]) {
super(); super();
this._parent = parent; this._parent = parent;
} }

View File

@ -1,30 +1,14 @@
import { import {Directive, Host, Inject, OnChanges, OnDestroy, Optional, Self, SimpleChanges, SkipSelf, forwardRef} from '@angular/core';
OnChanges,
OnDestroy,
SimpleChanges,
Directive,
forwardRef,
Host,
SkipSelf,
Inject,
Optional,
Self
} from '@angular/core';
import {EventEmitter, ObservableWrapper} from '../../facade/async'; import {EventEmitter, ObservableWrapper} from '../../facade/async';
import {ControlContainer} from './control_container';
import {NgControl} from './ng_control';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {
controlPath,
composeValidators,
composeAsyncValidators,
isPropertyUpdated,
selectValueAccessor
} from './shared';
import {Control} from '../model'; import {Control} from '../model';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';
import {ValidatorFn, AsyncValidatorFn} from './validators';
import {ControlContainer} from './control_container';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {NgControl} from './ng_control';
import {composeAsyncValidators, composeValidators, controlPath, isPropertyUpdated, selectValueAccessor} from './shared';
import {AsyncValidatorFn, ValidatorFn} from './validators';
export const controlNameBinding: any = export const controlNameBinding: any =
@ -112,35 +96,37 @@ export class NgControlName extends NgControl implements OnChanges,
/* Array<Validator|Function> */ any[], /* Array<Validator|Function> */ any[],
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) @Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
valueAccessors: ControlValueAccessor[]) { valueAccessors: ControlValueAccessor[]) {
super(); super();
this.valueAccessor = selectValueAccessor(this, valueAccessors); this.valueAccessor = selectValueAccessor(this, valueAccessors);
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
if (!this._added) { if (!this._added) {
this.formDirective.addControl(this); this.formDirective.addControl(this);
this._added = true; this._added = true;
} }
if (isPropertyUpdated(changes, this.viewModel)) { if (isPropertyUpdated(changes, this.viewModel)) {
this.viewModel = this.model; this.viewModel = this.model;
this.formDirective.updateModel(this, this.model); this.formDirective.updateModel(this, this.model);
} }
} }
ngOnDestroy(): void { this.formDirective.removeControl(this); } ngOnDestroy(): void { this.formDirective.removeControl(this); }
viewToModelUpdate(newValue: any): void { viewToModelUpdate(newValue: any): void {
this.viewModel = newValue; this.viewModel = newValue;
ObservableWrapper.callEmit(this.update, newValue); ObservableWrapper.callEmit(this.update, 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.formDirective; } get formDirective(): any { return this._parent.formDirective; }
get validator(): ValidatorFn { return composeValidators(this._validators); } get validator(): ValidatorFn { return composeValidators(this._validators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); } get asyncValidator(): AsyncValidatorFn {
return composeAsyncValidators(this._asyncValidators);
}
get control(): Control { return this.formDirective.getControl(this); } get control(): Control { return this.formDirective.getControl(this); }
} }

View File

@ -1,7 +1,10 @@
import {Directive, Self} from '@angular/core'; import {Directive, Self} from '@angular/core';
import {NgControl} from './ng_control';
import {isPresent} from '../../facade/lang'; import {isPresent} from '../../facade/lang';
import {NgControl} from './ng_control';
/** /**
* Directive automatically applied to Angular forms that sets CSS classes * Directive automatically applied to Angular forms that sets CSS classes
* based on control status (valid/invalid/dirty/etc). * based on control status (valid/invalid/dirty/etc).

View File

@ -1,18 +1,16 @@
import {Directive, forwardRef, Optional, Inject, Self} from '@angular/core'; import {Directive, Inject, Optional, Self, forwardRef} from '@angular/core';
import {
PromiseWrapper, import {EventEmitter, ObservableWrapper, PromiseWrapper} from '../../facade/async';
ObservableWrapper,
EventEmitter
} from '../../facade/async';
import {ListWrapper} from '../../facade/collection'; import {ListWrapper} from '../../facade/collection';
import {isPresent} from '../../facade/lang'; import {isPresent} from '../../facade/lang';
import {NgControl} from './ng_control'; import {AbstractControl, Control, ControlGroup} from '../model';
import {Form} from './form_interface'; import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';
import {NgControlGroup} from './ng_control_group';
import {ControlContainer} from './control_container'; import {ControlContainer} from './control_container';
import {AbstractControl, ControlGroup, Control} from '../model'; import {Form} from './form_interface';
import {setUpControl, setUpControlGroup, composeValidators, composeAsyncValidators} from './shared'; import {NgControl} from './ng_control';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {NgControlGroup} from './ng_control_group';
import {composeAsyncValidators, composeValidators, setUpControl, setUpControlGroup} from './shared';
export const formDirectiveProvider: any = export const formDirectiveProvider: any =
/*@ts2dart_const*/ {provide: ControlContainer, useExisting: forwardRef(() => NgForm)}; /*@ts2dart_const*/ {provide: ControlContainer, useExisting: forwardRef(() => NgForm)};
@ -93,11 +91,12 @@ export class NgForm extends ControlContainer implements Form {
form: ControlGroup; form: ControlGroup;
ngSubmit = new EventEmitter(); ngSubmit = new EventEmitter();
constructor(@Optional() @Self() @Inject(NG_VALIDATORS) validators: any[], constructor(
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: any[]) { @Optional() @Self() @Inject(NG_VALIDATORS) validators: any[],
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: any[]) {
super(); super();
this.form = new ControlGroup({}, null, composeValidators(validators), this.form = new ControlGroup(
composeAsyncValidators(asyncValidators)); {}, null, composeValidators(validators), composeAsyncValidators(asyncValidators));
} }
get submitted(): boolean { return this._submitted; } get submitted(): boolean { return this._submitted; }

View File

@ -1,28 +1,14 @@
import { import {Directive, Inject, OnChanges, Optional, Self, SimpleChanges, forwardRef} from '@angular/core';
OnChanges,
SimpleChanges,
Directive,
forwardRef,
Inject,
Optional,
Self
} from '@angular/core';
import {StringMapWrapper} from '../../facade/collection';
import {EventEmitter, ObservableWrapper} from '../../facade/async'; import {EventEmitter, ObservableWrapper} from '../../facade/async';
import {StringMapWrapper} from '../../facade/collection';
import {NgControl} from './ng_control';
import {Control} from '../model'; import {Control} from '../model';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor'; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import { import {NgControl} from './ng_control';
setUpControl, import {composeAsyncValidators, composeValidators, isPropertyUpdated, selectValueAccessor, setUpControl} from './shared';
composeValidators, import {AsyncValidatorFn, ValidatorFn} from './validators';
composeAsyncValidators,
isPropertyUpdated,
selectValueAccessor
} from './shared';
import {ValidatorFn, AsyncValidatorFn} from './validators';
export const formControlBinding: any = export const formControlBinding: any =
/*@ts2dart_const*/ /* @ts2dart_Provider */ { /*@ts2dart_const*/ /* @ts2dart_Provider */ {
@ -98,35 +84,37 @@ export class NgFormControl extends NgControl implements OnChanges {
/* Array<Validator|Function> */ any[], /* Array<Validator|Function> */ any[],
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) @Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
valueAccessors: ControlValueAccessor[]) { valueAccessors: ControlValueAccessor[]) {
super(); super();
this.valueAccessor = selectValueAccessor(this, valueAccessors); this.valueAccessor = selectValueAccessor(this, valueAccessors);
} }
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
if (this._isControlChanged(changes)) { if (this._isControlChanged(changes)) {
setUpControl(this.form, this); setUpControl(this.form, this);
this.form.updateValueAndValidity({emitEvent: false}); this.form.updateValueAndValidity({emitEvent: false});
} }
if (isPropertyUpdated(changes, this.viewModel)) { if (isPropertyUpdated(changes, this.viewModel)) {
this.form.updateValue(this.model); this.form.updateValue(this.model);
this.viewModel = this.model; this.viewModel = this.model;
} }
} }
get path(): string[] { return []; } get path(): string[] { return []; }
get validator(): ValidatorFn { return composeValidators(this._validators); } get validator(): ValidatorFn { return composeValidators(this._validators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); } get asyncValidator(): AsyncValidatorFn {
return composeAsyncValidators(this._asyncValidators);
}
get control(): Control { return this.form; } get control(): Control { return this.form; }
viewToModelUpdate(newValue: any): void { viewToModelUpdate(newValue: any): void {
this.viewModel = newValue; this.viewModel = newValue;
ObservableWrapper.callEmit(this.update, newValue); ObservableWrapper.callEmit(this.update, newValue);
} }
private _isControlChanged(changes: {[key: string]: any}): boolean { private _isControlChanged(changes: {[key: string]: any}): boolean {
return StringMapWrapper.contains(changes, "form"); return StringMapWrapper.contains(changes, 'form');
} }
} }

View File

@ -1,23 +1,17 @@
import { import {Directive, Inject, OnChanges, Optional, Self, SimpleChanges, forwardRef} from '@angular/core';
SimpleChanges,
OnChanges, import {EventEmitter, ObservableWrapper} from '../../facade/async';
Directive,
forwardRef,
Inject,
Optional,
Self
} from '@angular/core';
import {isBlank} from '../../facade/lang';
import {ListWrapper, StringMapWrapper} from '../../facade/collection'; import {ListWrapper, StringMapWrapper} from '../../facade/collection';
import {BaseException} from '../../facade/exceptions'; import {BaseException} from '../../facade/exceptions';
import {ObservableWrapper, EventEmitter} from '../../facade/async'; import {isBlank} from '../../facade/lang';
import {NgControl} from './ng_control'; import {Control, ControlGroup} from '../model';
import {NgControlGroup} from './ng_control_group'; import {NG_ASYNC_VALIDATORS, NG_VALIDATORS, Validators} from '../validators';
import {ControlContainer} from './control_container'; import {ControlContainer} from './control_container';
import {Form} from './form_interface'; import {Form} from './form_interface';
import {Control, ControlGroup} from '../model'; import {NgControl} from './ng_control';
import {setUpControl, setUpControlGroup, composeValidators, composeAsyncValidators} from './shared'; import {NgControlGroup} from './ng_control_group';
import {Validators, NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {composeAsyncValidators, composeValidators, setUpControl, setUpControlGroup} from './shared';
export const formDirectiveProvider: any = export const formDirectiveProvider: any =
/*@ts2dart_const*/ /* @ts2dart_Provider */ { /*@ts2dart_const*/ /* @ts2dart_Provider */ {
@ -115,14 +109,15 @@ export class NgFormModel extends ControlContainer implements Form,
directives: NgControl[] = []; directives: NgControl[] = [];
ngSubmit = new EventEmitter(); ngSubmit = new EventEmitter();
constructor(@Optional() @Self() @Inject(NG_VALIDATORS) private _validators: any[], constructor(
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[]) { @Optional() @Self() @Inject(NG_VALIDATORS) private _validators: any[],
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[]) {
super(); super();
} }
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
this._checkFormPresent(); this._checkFormPresent();
if (StringMapWrapper.contains(changes, "form")) { if (StringMapWrapper.contains(changes, 'form')) {
var sync = composeValidators(this._validators); var sync = composeValidators(this._validators);
this.form.validator = Validators.compose([this.form.validator, sync]); this.form.validator = Validators.compose([this.form.validator, sync]);

View File

@ -1,25 +1,13 @@
import { import {Directive, Inject, OnChanges, Optional, Self, SimpleChanges, forwardRef} from '@angular/core';
OnChanges,
SimpleChanges,
Directive,
forwardRef,
Inject,
Optional,
Self
} from '@angular/core';
import {EventEmitter, ObservableWrapper} from '../../facade/async'; import {EventEmitter, ObservableWrapper} from '../../facade/async';
import {Control} from '../model';
import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor'; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {NgControl} from './ng_control'; import {NgControl} from './ng_control';
import {Control} from '../model'; import {composeAsyncValidators, composeValidators, isPropertyUpdated, selectValueAccessor, setUpControl} from './shared';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {AsyncValidatorFn, ValidatorFn} from './validators';
import {
setUpControl,
isPropertyUpdated,
selectValueAccessor,
composeValidators,
composeAsyncValidators
} from './shared';
import {ValidatorFn, AsyncValidatorFn} from './validators';
export const formControlBinding: any = export const formControlBinding: any =
/*@ts2dart_const*/ /* @ts2dart_Provider */ { /*@ts2dart_const*/ /* @ts2dart_Provider */ {
@ -70,33 +58,35 @@ export class NgModel extends NgControl implements OnChanges {
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[], @Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[],
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) @Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
valueAccessors: ControlValueAccessor[]) { valueAccessors: ControlValueAccessor[]) {
super(); super();
this.valueAccessor = selectValueAccessor(this, valueAccessors); this.valueAccessor = selectValueAccessor(this, valueAccessors);
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
if (!this._added) { if (!this._added) {
setUpControl(this._control, this); setUpControl(this._control, this);
this._control.updateValueAndValidity({emitEvent: false}); this._control.updateValueAndValidity({emitEvent: false});
this._added = true; this._added = true;
} }
if (isPropertyUpdated(changes, this.viewModel)) { if (isPropertyUpdated(changes, this.viewModel)) {
this._control.updateValue(this.model); this._control.updateValue(this.model);
this.viewModel = this.model; this.viewModel = this.model;
} }
} }
get control(): Control { return this._control; } get control(): Control { return this._control; }
get path(): string[] { return []; } get path(): string[] { return []; }
get validator(): ValidatorFn { return composeValidators(this._validators); } get validator(): ValidatorFn { return composeValidators(this._validators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); } get asyncValidator(): AsyncValidatorFn {
return composeAsyncValidators(this._asyncValidators);
}
viewToModelUpdate(newValue: any): void { viewToModelUpdate(newValue: any): void {
this.viewModel = newValue; this.viewModel = newValue;
ObservableWrapper.callEmit(this.update, newValue); ObservableWrapper.callEmit(this.update, newValue);
} }
} }

View File

@ -1,5 +1,6 @@
import {AbstractControl} from '../model'; import {AbstractControl} from '../model';
import {Validator, ValidatorFn, AsyncValidatorFn} from './validators';
import {AsyncValidatorFn, Validator, ValidatorFn} from './validators';
export function normalizeValidator(validator: ValidatorFn | Validator): ValidatorFn { export function normalizeValidator(validator: ValidatorFn | Validator): ValidatorFn {
if ((<Validator>validator).validate !== undefined) { if ((<Validator>validator).validate !== undefined) {

View File

@ -1,6 +1,8 @@
import {Directive, ElementRef, Renderer, forwardRef} from '@angular/core'; import {Directive, ElementRef, Renderer, forwardRef} from '@angular/core';
import {NumberWrapper} from '../../facade/lang'; import {NumberWrapper} from '../../facade/lang';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from './control_value_accessor';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
export const NUMBER_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ { export const NUMBER_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

View File

@ -1,17 +1,9 @@
import { import {Directive, ElementRef, Injectable, Injector, Input, OnDestroy, OnInit, Renderer, forwardRef} from '@angular/core';
Directive,
ElementRef,
Renderer,
forwardRef,
Input,
OnInit,
OnDestroy,
Injector,
Injectable
} from '@angular/core';
import {isPresent} from '../../facade/lang';
import {ListWrapper} from '../../facade/collection'; import {ListWrapper} from '../../facade/collection';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from './control_value_accessor'; import {isPresent} from '../../facade/lang';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {NgControl} from './ng_control'; import {NgControl} from './ng_control';
export const RADIO_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ { export const RADIO_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ {
@ -49,10 +41,10 @@ export class RadioControlRegistry {
}); });
} }
private _isSameGroup(controlPair:[NgControl, RadioControlValueAccessor], private _isSameGroup(
accessor: RadioControlValueAccessor) { controlPair: [NgControl, RadioControlValueAccessor], accessor: RadioControlValueAccessor) {
return controlPair[0].control.root === accessor._control.control.root && return controlPair[0].control.root === accessor._control.control.root &&
controlPair[1].name === accessor.name; controlPair[1].name === accessor.name;
} }
} }
@ -102,8 +94,9 @@ export class RadioControlValueAccessor implements ControlValueAccessor,
onChange = () => {}; onChange = () => {};
onTouched = () => {}; onTouched = () => {};
constructor(private _renderer: Renderer, private _elementRef: ElementRef, constructor(
private _registry: RadioControlRegistry, private _injector: Injector) {} private _renderer: Renderer, private _elementRef: ElementRef,
private _registry: RadioControlRegistry, private _injector: Injector) {}
ngOnInit(): void { ngOnInit(): void {
this._control = this._injector.get(NgControl); this._control = this._injector.get(NgControl);

View File

@ -1,23 +1,9 @@
import { import {Directive, ElementRef, Host, Input, OnDestroy, Optional, Renderer, forwardRef} from '@angular/core';
Directive,
Renderer,
forwardRef,
ElementRef,
Input,
Host,
OnDestroy,
Optional
} from '@angular/core';
import {
StringWrapper,
isPrimitive,
isPresent,
isBlank,
looseIdentical
} from '../../facade/lang';
import {MapWrapper} from '../../facade/collection';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from './control_value_accessor'; import {MapWrapper} from '../../facade/collection';
import {StringWrapper, isBlank, isPresent, isPrimitive, looseIdentical} from '../../facade/lang';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
export const SELECT_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ { export const SELECT_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
@ -27,12 +13,12 @@ export const SELECT_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider
function _buildValueString(id: string, value: any): string { function _buildValueString(id: string, value: any): string {
if (isBlank(id)) return `${value}`; if (isBlank(id)) return `${value}`;
if (!isPrimitive(value)) value = "Object"; if (!isPrimitive(value)) value = 'Object';
return StringWrapper.slice(`${id}: ${value}`, 0, 50); return StringWrapper.slice(`${id}: ${value}`, 0, 50);
} }
function _extractId(valueString: string): string { function _extractId(valueString: string): string {
return valueString.split(":")[0]; return valueString.split(':')[0];
} }
/** /**
@ -112,8 +98,9 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
export class NgSelectOption implements OnDestroy { export class NgSelectOption implements OnDestroy {
id: string; id: string;
constructor(private _element: ElementRef, private _renderer: Renderer, constructor(
@Optional() @Host() private _select: SelectControlValueAccessor) { private _element: ElementRef, private _renderer: Renderer,
@Optional() @Host() private _select: SelectControlValueAccessor) {
if (isPresent(this._select)) this.id = this._select._registerOption(); if (isPresent(this._select)) this.id = this._select._registerOption();
} }

View File

@ -1,23 +1,9 @@
import { import {Directive, ElementRef, Host, Input, OnDestroy, Optional, Renderer, forwardRef} from '@angular/core';
Input,
Directive,
ElementRef,
Renderer,
Optional,
Host,
OnDestroy,
forwardRef
} from "@angular/core";
import {
isBlank,
isPrimitive,
StringWrapper,
isPresent,
looseIdentical,
isString
} from '../../facade/lang';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {MapWrapper} from '../../facade/collection'; import {MapWrapper} from '../../facade/collection';
import {StringWrapper, isBlank, isPresent, isPrimitive, isString, looseIdentical} from '../../facade/lang';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
const SELECT_MULTIPLE_VALUE_ACCESSOR = { const SELECT_MULTIPLE_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
@ -28,12 +14,12 @@ const SELECT_MULTIPLE_VALUE_ACCESSOR = {
function _buildValueString(id: string, value: any): string { function _buildValueString(id: string, value: any): string {
if (isBlank(id)) return `${value}`; if (isBlank(id)) return `${value}`;
if (isString(value)) value = `'${value}'`; if (isString(value)) value = `'${value}'`;
if (!isPrimitive(value)) value = "Object"; if (!isPrimitive(value)) value = 'Object';
return StringWrapper.slice(`${id}: ${value}`, 0, 50); return StringWrapper.slice(`${id}: ${value}`, 0, 50);
} }
function _extractId(valueString: string): string { function _extractId(valueString: string): string {
return valueString.split(":")[0]; return valueString.split(':')[0];
} }
/** Mock interface for HTML Options */ /** Mock interface for HTML Options */
@ -74,9 +60,7 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
let values: Array<any> = <Array<any>>value; let values: Array<any> = <Array<any>>value;
// convert values to ids // convert values to ids
let ids = values.map((v) => this._getOptionId(v)); let ids = values.map((v) => this._getOptionId(v));
this._optionMap.forEach((opt, o) => { this._optionMap.forEach((opt, o) => { opt._setSelected(ids.indexOf(o.toString()) > -1); });
opt._setSelected(ids.indexOf(o.toString()) > -1);
});
} }
registerOnChange(fn: (value: any) => any): void { registerOnChange(fn: (value: any) => any): void {
@ -108,7 +92,7 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
/** @internal */ /** @internal */
_registerOption(value: NgSelectMultipleOption): string { _registerOption(value: NgSelectMultipleOption): string {
let id:string = (this._idCounter++).toString(); let id: string = (this._idCounter++).toString();
this._optionMap.set(id, value); this._optionMap.set(id, value);
return id; return id;
} }
@ -145,8 +129,9 @@ export class NgSelectMultipleOption implements OnDestroy {
/** @internal */ /** @internal */
_value: any; _value: any;
constructor(private _element: ElementRef, private _renderer: Renderer, constructor(
@Optional() @Host() private _select: SelectMultipleControlValueAccessor) { private _element: ElementRef, private _renderer: Renderer,
@Optional() @Host() private _select: SelectMultipleControlValueAccessor) {
if (isPresent(this._select)) { if (isPresent(this._select)) {
this.id = this._select._registerOption(this); this.id = this._select._registerOption(this);
} }

View File

@ -1,21 +1,21 @@
import {ListWrapper, StringMapWrapper} from '../../facade/collection'; import {ListWrapper, StringMapWrapper} from '../../facade/collection';
import {isBlank, isPresent, looseIdentical, hasConstructor} from '../../facade/lang';
import {BaseException} from '../../facade/exceptions'; import {BaseException} from '../../facade/exceptions';
import {hasConstructor, isBlank, isPresent, looseIdentical} from '../../facade/lang';
import {ControlContainer} from './control_container';
import {NgControl} from './ng_control';
import {AbstractControlDirective} from './abstract_control_directive';
import {NgControlGroup} from './ng_control_group';
import {Control, ControlGroup} from '../model'; import {Control, ControlGroup} from '../model';
import {Validators} from '../validators'; import {Validators} from '../validators';
import {AbstractControlDirective} from './abstract_control_directive';
import {CheckboxControlValueAccessor} from './checkbox_value_accessor';
import {ControlContainer} from './control_container';
import {ControlValueAccessor} from './control_value_accessor'; import {ControlValueAccessor} from './control_value_accessor';
import {DefaultValueAccessor} from './default_value_accessor'; import {DefaultValueAccessor} from './default_value_accessor';
import {NgControl} from './ng_control';
import {NgControlGroup} from './ng_control_group';
import {normalizeAsyncValidator, normalizeValidator} from './normalize_validator';
import {NumberValueAccessor} from './number_value_accessor'; import {NumberValueAccessor} from './number_value_accessor';
import {CheckboxControlValueAccessor} from './checkbox_value_accessor';
import {SelectControlValueAccessor} from './select_control_value_accessor';
import {RadioControlValueAccessor} from './radio_control_value_accessor'; import {RadioControlValueAccessor} from './radio_control_value_accessor';
import {normalizeValidator, normalizeAsyncValidator} from './normalize_validator'; import {SelectControlValueAccessor} from './select_control_value_accessor';
import {ValidatorFn, AsyncValidatorFn} from './validators'; import {AsyncValidatorFn, ValidatorFn} from './validators';
export function controlPath(name: string, parent: ControlContainer): string[] { export function controlPath(name: string, parent: ControlContainer): string[] {
@ -25,8 +25,8 @@ export function controlPath(name: string, parent: ControlContainer): string[] {
} }
export function setUpControl(control: Control, dir: NgControl): void { export function setUpControl(control: Control, dir: NgControl): void {
if (isBlank(control)) _throwError(dir, "Cannot find control"); if (isBlank(control)) _throwError(dir, 'Cannot find control');
if (isBlank(dir.valueAccessor)) _throwError(dir, "No value accessor for"); if (isBlank(dir.valueAccessor)) _throwError(dir, 'No value accessor for');
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]);
@ -47,13 +47,13 @@ export function setUpControl(control: Control, dir: NgControl): void {
} }
export function setUpControlGroup(control: ControlGroup, dir: NgControlGroup) { export function setUpControlGroup(control: ControlGroup, dir: NgControlGroup) {
if (isBlank(control)) _throwError(dir, "Cannot find control"); if (isBlank(control)) _throwError(dir, 'Cannot find control');
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]);
} }
function _throwError(dir: AbstractControlDirective, message: string): void { function _throwError(dir: AbstractControlDirective, message: string): void {
var path = dir.path.join(" -> "); var path = dir.path.join(' -> ');
throw new BaseException(`${message} '${path}'`); throw new BaseException(`${message} '${path}'`);
} }
@ -61,23 +61,23 @@ export function composeValidators(validators: /* Array<Validator|Function> */ an
return isPresent(validators) ? Validators.compose(validators.map(normalizeValidator)) : null; return isPresent(validators) ? Validators.compose(validators.map(normalizeValidator)) : null;
} }
export function composeAsyncValidators( export function composeAsyncValidators(validators: /* Array<Validator|Function> */ any[]):
validators: /* Array<Validator|Function> */ any[]): AsyncValidatorFn { AsyncValidatorFn {
return isPresent(validators) ? Validators.composeAsync(validators.map(normalizeAsyncValidator)) : return isPresent(validators) ? Validators.composeAsync(validators.map(normalizeAsyncValidator)) :
null; null;
} }
export function isPropertyUpdated(changes: {[key: string]: any}, viewModel: any): boolean { export function isPropertyUpdated(changes: {[key: string]: any}, viewModel: any): boolean {
if (!StringMapWrapper.contains(changes, "model")) return false; if (!StringMapWrapper.contains(changes, 'model')) return false;
var change = changes["model"]; var change = changes['model'];
if (change.isFirstChange()) return true; if (change.isFirstChange()) return true;
return !looseIdentical(viewModel, change.currentValue); return !looseIdentical(viewModel, change.currentValue);
} }
// 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(dir: NgControl, export function selectValueAccessor(
valueAccessors: ControlValueAccessor[]): ControlValueAccessor { dir: NgControl, valueAccessors: ControlValueAccessor[]): ControlValueAccessor {
if (isBlank(valueAccessors)) return null; if (isBlank(valueAccessors)) return null;
var defaultAccessor: ControlValueAccessor; var defaultAccessor: ControlValueAccessor;
@ -87,17 +87,17 @@ export function selectValueAccessor(dir: NgControl,
if (hasConstructor(v, DefaultValueAccessor)) { if (hasConstructor(v, DefaultValueAccessor)) {
defaultAccessor = v; defaultAccessor = v;
} else if (hasConstructor(v, CheckboxControlValueAccessor) || } else if (
hasConstructor(v, NumberValueAccessor) || hasConstructor(v, CheckboxControlValueAccessor) || hasConstructor(v, NumberValueAccessor) ||
hasConstructor(v, SelectControlValueAccessor) || hasConstructor(v, SelectControlValueAccessor) ||
hasConstructor(v, RadioControlValueAccessor)) { hasConstructor(v, RadioControlValueAccessor)) {
if (isPresent(builtinAccessor)) if (isPresent(builtinAccessor))
_throwError(dir, "More than one built-in value accessor matches"); _throwError(dir, 'More than one built-in value accessor matches');
builtinAccessor = v; builtinAccessor = v;
} else { } else {
if (isPresent(customAccessor)) if (isPresent(customAccessor))
_throwError(dir, "More than one custom value accessor matches"); _throwError(dir, 'More than one custom value accessor matches');
customAccessor = v; customAccessor = v;
} }
}); });
@ -106,6 +106,6 @@ export function selectValueAccessor(dir: NgControl,
if (isPresent(builtinAccessor)) return builtinAccessor; if (isPresent(builtinAccessor)) return builtinAccessor;
if (isPresent(defaultAccessor)) return defaultAccessor; if (isPresent(defaultAccessor)) return defaultAccessor;
_throwError(dir, "No valid value accessor for"); _throwError(dir, 'No valid value accessor for');
return null; return null;
} }

View File

@ -1,7 +1,8 @@
import {forwardRef, Attribute, Directive} from '@angular/core'; import {Attribute, Directive, forwardRef} from '@angular/core';
import {NumberWrapper} from '../../facade/lang'; import {NumberWrapper} from '../../facade/lang';
import {Validators, NG_VALIDATORS} from '../validators';
import {AbstractControl} from '../model'; import {AbstractControl} from '../model';
import {NG_VALIDATORS, Validators} from '../validators';
@ -82,7 +83,7 @@ export const MIN_LENGTH_VALIDATOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*
export class MinLengthValidator implements Validator { export class MinLengthValidator implements Validator {
private _validator: ValidatorFn; private _validator: ValidatorFn;
constructor(@Attribute("minlength") minLength: string) { constructor(@Attribute('minlength') minLength: string) {
this._validator = Validators.minLength(NumberWrapper.parseInt(minLength, 10)); this._validator = Validators.minLength(NumberWrapper.parseInt(minLength, 10));
} }
@ -115,7 +116,7 @@ export const MAX_LENGTH_VALIDATOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*
export class MaxLengthValidator implements Validator { export class MaxLengthValidator implements Validator {
private _validator: ValidatorFn; private _validator: ValidatorFn;
constructor(@Attribute("maxlength") maxLength: string) { constructor(@Attribute('maxlength') maxLength: string) {
this._validator = Validators.maxLength(NumberWrapper.parseInt(maxLength, 10)); this._validator = Validators.maxLength(NumberWrapper.parseInt(maxLength, 10));
} }
@ -150,7 +151,7 @@ export const PATTERN_VALIDATOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ {
export class PatternValidator implements Validator { export class PatternValidator implements Validator {
private _validator: ValidatorFn; private _validator: ValidatorFn;
constructor(@Attribute("pattern") pattern: string) { constructor(@Attribute('pattern') pattern: string) {
this._validator = Validators.pattern(pattern); this._validator = Validators.pattern(pattern);
} }

View File

@ -1,8 +1,11 @@
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {StringMapWrapper} from '../facade/collection'; import {StringMapWrapper} from '../facade/collection';
import {isPresent, isArray} from '../facade/lang'; import {isArray, isPresent} from '../facade/lang';
import {AsyncValidatorFn, ValidatorFn} from './directives/validators';
import * as modelModule from './model'; import * as modelModule from './model';
import {ValidatorFn, AsyncValidatorFn} from './directives/validators';
/** /**
@ -56,21 +59,21 @@ export class FormBuilder {
* *
* See the {@link ControlGroup} constructor for more details. * See the {@link ControlGroup} constructor for more details.
*/ */
group(controlsConfig: {[key: string]: any}, group(controlsConfig: {[key: string]: any}, extra: {[key: string]: any} = null):
extra: {[key: string]: any} = null): modelModule.ControlGroup { modelModule.ControlGroup {
var controls = this._reduceControls(controlsConfig); var controls = this._reduceControls(controlsConfig);
var optionals = <{[key: string]: boolean}>( var optionals = <{[key: string]: boolean}>(
isPresent(extra) ? StringMapWrapper.get(extra, "optionals") : null); isPresent(extra) ? StringMapWrapper.get(extra, 'optionals') : null);
var validator: ValidatorFn = isPresent(extra) ? StringMapWrapper.get(extra, "validator") : null; var validator: ValidatorFn = isPresent(extra) ? StringMapWrapper.get(extra, 'validator') : null;
var asyncValidator: AsyncValidatorFn = var asyncValidator: AsyncValidatorFn =
isPresent(extra) ? StringMapWrapper.get(extra, "asyncValidator") : null; isPresent(extra) ? StringMapWrapper.get(extra, 'asyncValidator') : null;
return new modelModule.ControlGroup(controls, optionals, validator, asyncValidator); return new modelModule.ControlGroup(controls, optionals, validator, asyncValidator);
} }
/** /**
* Construct a new {@link Control} with the given `value`,`validator`, and `asyncValidator`. * Construct a new {@link Control} with the given `value`,`validator`, and `asyncValidator`.
*/ */
control(value: Object, validator: ValidatorFn = null, control(value: Object, validator: ValidatorFn = null, asyncValidator: AsyncValidatorFn = null):
asyncValidator: AsyncValidatorFn = null): modelModule.Control { modelModule.Control {
return new modelModule.Control(value, validator, asyncValidator); return new modelModule.Control(value, validator, asyncValidator);
} }
@ -78,15 +81,16 @@ export class FormBuilder {
* Construct an array of {@link Control}s from the given `controlsConfig` array of * Construct an array of {@link Control}s from the given `controlsConfig` array of
* configuration, with the given optional `validator` and `asyncValidator`. * configuration, with the given optional `validator` and `asyncValidator`.
*/ */
array(controlsConfig: any[], validator: ValidatorFn = null, array(
asyncValidator: AsyncValidatorFn = null): modelModule.ControlArray { controlsConfig: any[], validator: ValidatorFn = null,
asyncValidator: AsyncValidatorFn = null): modelModule.ControlArray {
var controls = controlsConfig.map(c => this._createControl(c)); var controls = controlsConfig.map(c => this._createControl(c));
return new modelModule.ControlArray(controls, validator, asyncValidator); return new modelModule.ControlArray(controls, validator, asyncValidator);
} }
/** @internal */ /** @internal */
_reduceControls(controlsConfig: {[k: string]: _reduceControls(controlsConfig: {[k: string]: any}):
any}): {[key: string]: modelModule.AbstractControl} { {[key: string]: modelModule.AbstractControl} {
var controls: {[key: string]: modelModule.AbstractControl} = {}; var controls: {[key: string]: modelModule.AbstractControl} = {};
StringMapWrapper.forEach(controlsConfig, (controlConfig: any, controlName: string) => { StringMapWrapper.forEach(controlsConfig, (controlConfig: any, controlName: string) => {
controls[controlName] = this._createControl(controlConfig); controls[controlName] = this._createControl(controlConfig);

View File

@ -1,48 +1,49 @@
import {isPresent, isBlank, normalizeBool} from '../facade/lang'; import {EventEmitter, Observable, ObservableWrapper} from '../facade/async';
import {Observable, EventEmitter, ObservableWrapper} from '../facade/async'; import {ListWrapper, StringMapWrapper} from '../facade/collection';
import {isBlank, isPresent, normalizeBool} from '../facade/lang';
import {PromiseWrapper} from '../facade/promise'; import {PromiseWrapper} from '../facade/promise';
import {StringMapWrapper, ListWrapper} from '../facade/collection';
import {ValidatorFn, AsyncValidatorFn} from './directives/validators'; import {AsyncValidatorFn, ValidatorFn} from './directives/validators';
/** /**
* Indicates that a Control is valid, i.e. that no errors exist in the input value. * Indicates that a Control is valid, i.e. that no errors exist in the input value.
*/ */
export const VALID = "VALID"; export const VALID = 'VALID';
/** /**
* Indicates that a Control is invalid, i.e. that an error exists in the input value. * Indicates that a Control is invalid, i.e. that an error exists in the input value.
*/ */
export const INVALID = "INVALID"; export const INVALID = 'INVALID';
/** /**
* Indicates that a Control is pending, i.e. that async validation is occurring and * Indicates that a Control is pending, i.e. that async validation is occurring and
* errors are not yet available for the input value. * errors are not yet available for the input value.
*/ */
export const PENDING = "PENDING"; export const PENDING = 'PENDING';
export function isControl(control: Object): boolean { export function isControl(control: Object): boolean {
return control instanceof AbstractControl; return control instanceof AbstractControl;
} }
function _find(control: AbstractControl, path: Array<string | number>| string) { function _find(control: AbstractControl, path: Array<string|number>| string) {
if (isBlank(path)) return null; if (isBlank(path)) return null;
if (!(path instanceof Array)) { if (!(path instanceof Array)) {
path = (<string>path).split("/"); path = (<string>path).split('/');
} }
if (path instanceof Array && ListWrapper.isEmpty(path)) return null; if (path instanceof Array && ListWrapper.isEmpty(path)) return null;
return (<Array<string | number>>path) return (<Array<string|number>>path).reduce((v, name) => {
.reduce((v, name) => { if (v instanceof ControlGroup) {
if (v instanceof ControlGroup) { return isPresent(v.controls[name]) ? v.controls[name] : null;
return isPresent(v.controls[name]) ? v.controls[name] : null; } else if (v instanceof ControlArray) {
} else if (v instanceof ControlArray) { var index = <number>name;
var index = <number>name; return isPresent(v.at(index)) ? v.at(index) : null;
return isPresent(v.at(index)) ? v.at(index) : null; } else {
} else { return null;
return null; }
} }, control);
}, control);
} }
function toObservable(r: any): Observable<any> { function toObservable(r: any): Observable<any> {
@ -62,7 +63,7 @@ export abstract class AbstractControl {
private _errors: {[key: string]: any}; private _errors: {[key: string]: any};
private _pristine: boolean = true; private _pristine: boolean = true;
private _touched: boolean = false; private _touched: boolean = false;
private _parent: ControlGroup | ControlArray; private _parent: ControlGroup|ControlArray;
private _asyncValidationSubscription: any; private _asyncValidationSubscription: any;
constructor(public validator: ValidatorFn, public asyncValidator: AsyncValidatorFn) {} constructor(public validator: ValidatorFn, public asyncValidator: AsyncValidatorFn) {}
@ -112,10 +113,10 @@ export abstract class AbstractControl {
} }
} }
setParent(parent: ControlGroup | ControlArray): void { this._parent = parent; } setParent(parent: ControlGroup|ControlArray): void { this._parent = parent; }
updateValueAndValidity( updateValueAndValidity({onlySelf, emitEvent}: {onlySelf?: boolean, emitEvent?: boolean} = {}):
{onlySelf, emitEvent}: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { void {
onlySelf = normalizeBool(onlySelf); onlySelf = normalizeBool(onlySelf);
emitEvent = isPresent(emitEvent) ? emitEvent : true; emitEvent = isPresent(emitEvent) ? emitEvent : true;
@ -196,7 +197,7 @@ export abstract class AbstractControl {
} }
} }
find(path: Array<string | number>| string): AbstractControl { return _find(this, path); } find(path: Array<string|number>|string): AbstractControl { return _find(this, path); }
getError(errorCode: string, path: string[] = null): any { getError(errorCode: string, path: string[] = null): any {
var control = isPresent(path) && !ListWrapper.isEmpty(path) ? this.find(path) : this; var control = isPresent(path) && !ListWrapper.isEmpty(path) ? this.find(path) : this;
@ -273,8 +274,8 @@ export class Control extends AbstractControl {
/** @internal */ /** @internal */
_onChange: Function; _onChange: Function;
constructor(value: any = null, validator: ValidatorFn = null, constructor(
asyncValidator: AsyncValidatorFn = null) { value: any = null, validator: ValidatorFn = null, asyncValidator: AsyncValidatorFn = null) {
super(validator, asyncValidator); super(validator, asyncValidator);
this._value = value; this._value = value;
this.updateValueAndValidity({onlySelf: true, emitEvent: false}); this.updateValueAndValidity({onlySelf: true, emitEvent: false});
@ -339,9 +340,9 @@ export class Control extends AbstractControl {
export class ControlGroup extends AbstractControl { export class ControlGroup extends AbstractControl {
private _optionals: {[key: string]: boolean}; private _optionals: {[key: string]: boolean};
constructor(public controls: {[key: string]: AbstractControl}, constructor(
optionals: {[key: string]: boolean} = null, validator: ValidatorFn = null, public controls: {[key: string]: AbstractControl}, optionals: {[key: string]: boolean} = null,
asyncValidator: AsyncValidatorFn = null) { validator: ValidatorFn = null, asyncValidator: AsyncValidatorFn = null) {
super(validator, asyncValidator); super(validator, asyncValidator);
this._optionals = isPresent(optionals) ? optionals : {}; this._optionals = isPresent(optionals) ? optionals : {};
this._initObservables(); this._initObservables();
@ -467,8 +468,9 @@ export class ControlGroup extends AbstractControl {
* @experimental * @experimental
*/ */
export class ControlArray extends AbstractControl { export class ControlArray extends AbstractControl {
constructor(public controls: AbstractControl[], validator: ValidatorFn = null, constructor(
asyncValidator: AsyncValidatorFn = null) { public controls: AbstractControl[], validator: ValidatorFn = null,
asyncValidator: AsyncValidatorFn = null) {
super(validator, asyncValidator); super(validator, asyncValidator);
this._initObservables(); this._initObservables();
this._setParentForControls(); this._setParentForControls();

View File

@ -1,10 +1,13 @@
import {OpaqueToken} from '@angular/core'; import {OpaqueToken} from '@angular/core';
import {isBlank, isPresent, isString} from '../facade/lang';
import {PromiseWrapper} from '../facade/promise';
import {ObservableWrapper} from '../facade/async'; import {ObservableWrapper} from '../facade/async';
import {StringMapWrapper} from '../facade/collection'; import {StringMapWrapper} from '../facade/collection';
import {isBlank, isPresent, isString} from '../facade/lang';
import {PromiseWrapper} from '../facade/promise';
import {AsyncValidatorFn, ValidatorFn} from './directives/validators';
import * as modelModule from './model'; import * as modelModule from './model';
import {ValidatorFn, AsyncValidatorFn} from './directives/validators';
/** /**
* Providers for validators to be used for {@link Control}s in a form. * Providers for validators to be used for {@link Control}s in a form.
@ -16,7 +19,7 @@ import {ValidatorFn, AsyncValidatorFn} from './directives/validators';
* {@example core/forms/ts/ng_validators/ng_validators.ts region='ng_validators'} * {@example core/forms/ts/ng_validators/ng_validators.ts region='ng_validators'}
* @experimental * @experimental
*/ */
export const NG_VALIDATORS: OpaqueToken = /*@ts2dart_const*/ new OpaqueToken("NgValidators"); export const NG_VALIDATORS: OpaqueToken = /*@ts2dart_const*/ new OpaqueToken('NgValidators');
/** /**
* Providers for asynchronous validators to be used for {@link Control}s * Providers for asynchronous validators to be used for {@link Control}s
@ -29,7 +32,7 @@ export const NG_VALIDATORS: OpaqueToken = /*@ts2dart_const*/ new OpaqueToken("Ng
* @experimental * @experimental
*/ */
export const NG_ASYNC_VALIDATORS: OpaqueToken = export const NG_ASYNC_VALIDATORS: OpaqueToken =
/*@ts2dart_const*/ new OpaqueToken("NgAsyncValidators"); /*@ts2dart_const*/ new OpaqueToken('NgAsyncValidators');
/** /**
* Provides a set of validators used by form controls. * Provides a set of validators used by form controls.
@ -50,9 +53,9 @@ export class Validators {
* Validator that requires controls to have a non-empty value. * Validator that requires controls to have a non-empty value.
*/ */
static required(control: modelModule.AbstractControl): {[key: string]: boolean} { static required(control: modelModule.AbstractControl): {[key: string]: boolean} {
return isBlank(control.value) || (isString(control.value) && control.value == "") ? return isBlank(control.value) || (isString(control.value) && control.value == '') ?
{"required": true} : {'required': true} :
null; null;
} }
/** /**
@ -63,8 +66,8 @@ export class Validators {
if (isPresent(Validators.required(control))) return null; if (isPresent(Validators.required(control))) return null;
var v: string = control.value; var v: string = control.value;
return v.length < minLength ? return v.length < minLength ?
{"minlength": {"requiredLength": minLength, "actualLength": v.length}} : {'minlength': {'requiredLength': minLength, 'actualLength': v.length}} :
null; null;
}; };
} }
@ -76,8 +79,8 @@ export class Validators {
if (isPresent(Validators.required(control))) return null; if (isPresent(Validators.required(control))) return null;
var v: string = control.value; var v: string = control.value;
return v.length > maxLength ? return v.length > maxLength ?
{"maxlength": {"requiredLength": maxLength, "actualLength": v.length}} : {'maxlength': {'requiredLength': maxLength, 'actualLength': v.length}} :
null; null;
}; };
} }
@ -90,7 +93,7 @@ export class Validators {
let regex = new RegExp(`^${pattern}$`); let regex = new RegExp(`^${pattern}$`);
let v: string = control.value; let v: string = control.value;
return regex.test(v) ? null : return regex.test(v) ? null :
{"pattern": {"requiredPattern": `^${pattern}$`, "actualValue": v}}; {'pattern': {'requiredPattern': `^${pattern}$`, 'actualValue': v}};
}; };
} }
@ -129,13 +132,13 @@ function _convertToPromise(obj: any): any {
return PromiseWrapper.isPromise(obj) ? obj : ObservableWrapper.toPromise(obj); return PromiseWrapper.isPromise(obj) ? obj : ObservableWrapper.toPromise(obj);
} }
function _executeValidators(control: modelModule.AbstractControl, function _executeValidators(
validators: ValidatorFn[]): any[] { control: modelModule.AbstractControl, validators: ValidatorFn[]): any[] {
return validators.map(v => v(control)); return validators.map(v => v(control));
} }
function _executeAsyncValidators(control: modelModule.AbstractControl, function _executeAsyncValidators(
validators: AsyncValidatorFn[]): any[] { control: modelModule.AbstractControl, validators: AsyncValidatorFn[]): any[] {
return validators.map(v => v(control)); return validators.map(v => v(control));
} }

View File

@ -10,39 +10,32 @@
* Forms providers are not included in default providers; you must import these providers * Forms providers are not included in default providers; you must import these providers
* explicitly. * explicitly.
*/ */
export {AbstractControl, Control, ControlGroup, ControlArray} from './forms/model'; import {Type} from '@angular/core';
import {RadioControlRegistry} from './forms/directives/radio_control_value_accessor';
import {FormBuilder} from './forms/form_builder';
export {FORM_DIRECTIVES, RadioButtonState} from './forms/directives';
export {AbstractControlDirective} from './forms/directives/abstract_control_directive'; export {AbstractControlDirective} from './forms/directives/abstract_control_directive';
export {Form} from './forms/directives/form_interface'; export {CheckboxControlValueAccessor} from './forms/directives/checkbox_value_accessor';
export {ControlContainer} from './forms/directives/control_container'; export {ControlContainer} from './forms/directives/control_container';
export {NgControlName} from './forms/directives/ng_control_name';
export {NgFormControl} from './forms/directives/ng_form_control';
export {NgModel} from './forms/directives/ng_model';
export {NgControl} from './forms/directives/ng_control';
export {NgControlGroup} from './forms/directives/ng_control_group';
export {NgFormModel} from './forms/directives/ng_form_model';
export {NgForm} from './forms/directives/ng_form';
export {ControlValueAccessor, NG_VALUE_ACCESSOR} from './forms/directives/control_value_accessor'; export {ControlValueAccessor, NG_VALUE_ACCESSOR} from './forms/directives/control_value_accessor';
export {DefaultValueAccessor} from './forms/directives/default_value_accessor'; export {DefaultValueAccessor} from './forms/directives/default_value_accessor';
export {Form} from './forms/directives/form_interface';
export {NgControl} from './forms/directives/ng_control';
export {NgControlGroup} from './forms/directives/ng_control_group';
export {NgControlName} from './forms/directives/ng_control_name';
export {NgControlStatus} from './forms/directives/ng_control_status'; export {NgControlStatus} from './forms/directives/ng_control_status';
export {CheckboxControlValueAccessor} from './forms/directives/checkbox_value_accessor'; export {NgForm} from './forms/directives/ng_form';
export { export {NgFormControl} from './forms/directives/ng_form_control';
NgSelectOption, export {NgFormModel} from './forms/directives/ng_form_model';
SelectControlValueAccessor export {NgModel} from './forms/directives/ng_model';
} from './forms/directives/select_control_value_accessor'; export {NgSelectOption, SelectControlValueAccessor} from './forms/directives/select_control_value_accessor';
export {FORM_DIRECTIVES, RadioButtonState} from './forms/directives'; export {MaxLengthValidator, MinLengthValidator, PatternValidator, RequiredValidator, Validator} from './forms/directives/validators';
export {NG_VALIDATORS, NG_ASYNC_VALIDATORS, Validators} from './forms/validators';
export {
RequiredValidator,
MinLengthValidator,
MaxLengthValidator,
PatternValidator,
Validator
} from './forms/directives/validators';
export {FormBuilder} from './forms/form_builder'; export {FormBuilder} from './forms/form_builder';
import {FormBuilder} from './forms/form_builder'; export {AbstractControl, Control, ControlArray, ControlGroup} from './forms/model';
import {RadioControlRegistry} from './forms/directives/radio_control_value_accessor'; export {NG_ASYNC_VALIDATORS, NG_VALIDATORS, Validators} from './forms/validators';
import {Type} from '@angular/core';
/** /**
* Shorthand set of providers used for building Angular forms. * Shorthand set of providers used for building Angular forms.

View File

@ -1,60 +1,37 @@
import {Type} from '@angular/core'; import {Type} from '@angular/core';
import {NgControlName} from './directives/ng_control_name';
import {NgFormControl} from './directives/ng_form_control';
import {NgModel} from './directives/ng_model';
import {NgControlGroup} from './directives/ng_control_group';
import {NgFormModel} from './directives/ng_form_model';
import {NgForm} from './directives/ng_form';
import {DefaultValueAccessor} from './directives/default_value_accessor';
import {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor'; import {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
import {DefaultValueAccessor} from './directives/default_value_accessor';
import {NgControlGroup} from './directives/ng_control_group';
import {NgControlName} from './directives/ng_control_name';
import {NgControlStatus} from './directives/ng_control_status';
import {NgForm} from './directives/ng_form';
import {NgFormControl} from './directives/ng_form_control';
import {NgFormModel} from './directives/ng_form_model';
import {NgModel} from './directives/ng_model';
import {NumberValueAccessor} from './directives/number_value_accessor'; import {NumberValueAccessor} from './directives/number_value_accessor';
import {RadioControlValueAccessor} from './directives/radio_control_value_accessor'; import {RadioControlValueAccessor} from './directives/radio_control_value_accessor';
import {NgControlStatus} from './directives/ng_control_status'; import {NgSelectOption, SelectControlValueAccessor} from './directives/select_control_value_accessor';
import { import {NgSelectMultipleOption, SelectMultipleControlValueAccessor} from './directives/select_multiple_control_value_accessor';
SelectControlValueAccessor, import {MaxLengthValidator, MinLengthValidator, PatternValidator, RequiredValidator} from './directives/validators';
NgSelectOption
} from './directives/select_control_value_accessor';
import {
SelectMultipleControlValueAccessor,
NgSelectMultipleOption
} from './directives/select_multiple_control_value_accessor';
import {
RequiredValidator,
MinLengthValidator,
MaxLengthValidator,
PatternValidator
} from './directives/validators';
export {NgControlName} from './directives/ng_control_name';
export {NgFormControl} from './directives/ng_form_control';
export {NgModel} from './directives/ng_model';
export {NgControlGroup} from './directives/ng_control_group';
export {NgFormModel} from './directives/ng_form_model';
export {NgForm} from './directives/ng_form';
export {DefaultValueAccessor} from './directives/default_value_accessor';
export {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor'; export {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor';
export {
RadioControlValueAccessor,
RadioButtonState
} from './directives/radio_control_value_accessor';
export {NumberValueAccessor} from './directives/number_value_accessor';
export {NgControlStatus} from './directives/ng_control_status';
export {
SelectControlValueAccessor,
NgSelectOption
} from './directives/select_control_value_accessor';
export {
SelectMultipleControlValueAccessor,
NgSelectMultipleOption
} from './directives/select_multiple_control_value_accessor';
export {
RequiredValidator,
MinLengthValidator,
MaxLengthValidator,
PatternValidator
} from './directives/validators';
export {NgControl} from './directives/ng_control';
export {ControlValueAccessor} from './directives/control_value_accessor'; export {ControlValueAccessor} from './directives/control_value_accessor';
export {DefaultValueAccessor} from './directives/default_value_accessor';
export {NgControl} from './directives/ng_control';
export {NgControlGroup} from './directives/ng_control_group';
export {NgControlName} from './directives/ng_control_name';
export {NgControlStatus} from './directives/ng_control_status';
export {NgForm} from './directives/ng_form';
export {NgFormControl} from './directives/ng_form_control';
export {NgFormModel} from './directives/ng_form_model';
export {NgModel} from './directives/ng_model';
export {NumberValueAccessor} from './directives/number_value_accessor';
export {RadioButtonState, RadioControlValueAccessor} from './directives/radio_control_value_accessor';
export {NgSelectOption, SelectControlValueAccessor} from './directives/select_control_value_accessor';
export {NgSelectMultipleOption, SelectMultipleControlValueAccessor} from './directives/select_multiple_control_value_accessor';
export {MaxLengthValidator, MinLengthValidator, PatternValidator, RequiredValidator} from './directives/validators';
/** /**
* *
@ -74,26 +51,13 @@ export {ControlValueAccessor} from './directives/control_value_accessor';
* @experimental * @experimental
*/ */
export const FORM_DIRECTIVES: Type[] = /*@ts2dart_const*/[ export const FORM_DIRECTIVES: Type[] = /*@ts2dart_const*/[
NgControlName, NgControlName, NgControlGroup,
NgControlGroup,
NgFormControl, NgFormControl, NgModel, NgFormModel, NgForm,
NgModel,
NgFormModel,
NgForm,
NgSelectOption, NgSelectOption, NgSelectMultipleOption, DefaultValueAccessor, NumberValueAccessor,
NgSelectMultipleOption, CheckboxControlValueAccessor, SelectControlValueAccessor, SelectMultipleControlValueAccessor,
DefaultValueAccessor, RadioControlValueAccessor, NgControlStatus,
NumberValueAccessor,
CheckboxControlValueAccessor,
SelectControlValueAccessor,
SelectMultipleControlValueAccessor,
RadioControlValueAccessor,
NgControlStatus,
RequiredValidator, RequiredValidator, MinLengthValidator, MaxLengthValidator, PatternValidator
MinLengthValidator,
MaxLengthValidator,
PatternValidator
]; ];

View File

@ -1,6 +1,7 @@
import {AbstractControl} from '../model';
import {isPresent} from '../../facade/lang';
import {unimplemented} from '../../facade/exceptions'; import {unimplemented} from '../../facade/exceptions';
import {isPresent} from '../../facade/lang';
import {AbstractControl} from '../model';
/** /**
* Base class for control directives. * Base class for control directives.

View File

@ -1,5 +1,6 @@
import {Directive, Renderer, ElementRef, forwardRef} from '@angular/core'; import {Directive, ElementRef, Renderer, forwardRef} from '@angular/core';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from './control_value_accessor';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
export const CHECKBOX_VALUE_ACCESSOR: any = /*@ts2dart_const*/ { export const CHECKBOX_VALUE_ACCESSOR: any = /*@ts2dart_const*/ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

View File

@ -1,5 +1,6 @@
import {Form} from './form_interface';
import {AbstractControlDirective} from './abstract_control_directive'; import {AbstractControlDirective} from './abstract_control_directive';
import {Form} from './form_interface';
/** /**
* A directive that contains multiple {@link NgControl}s. * A directive that contains multiple {@link NgControl}s.

View File

@ -34,4 +34,4 @@ export interface ControlValueAccessor {
* @experimental * @experimental
*/ */
export const NG_VALUE_ACCESSOR: OpaqueToken = export const NG_VALUE_ACCESSOR: OpaqueToken =
/*@ts2dart_const*/ new OpaqueToken("NgValueAccessor"); /*@ts2dart_const*/ new OpaqueToken('NgValueAccessor');

View File

@ -1,6 +1,8 @@
import {Directive, ElementRef, Renderer, forwardRef} from '@angular/core'; import {Directive, ElementRef, Renderer, forwardRef} from '@angular/core';
import {isBlank} from '../../facade/lang'; import {isBlank} from '../../facade/lang';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from './control_value_accessor';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
export const DEFAULT_VALUE_ACCESSOR: any = /*@ts2dart_const*/ export const DEFAULT_VALUE_ACCESSOR: any = /*@ts2dart_const*/
/* @ts2dart_Provider */ { /* @ts2dart_Provider */ {

View File

@ -1,6 +1,8 @@
import {Control, ControlGroup} from '../model';
import {NgControl} from './ng_control'; import {NgControl} from './ng_control';
import {NgControlGroup} from './ng_control_group'; import {NgControlGroup} from './ng_control_group';
import {Control, ControlGroup} from '../model';
/** /**
* An interface that {@link NgFormModel} and {@link NgForm} implement. * An interface that {@link NgFormModel} and {@link NgForm} implement.

View File

@ -1,9 +1,10 @@
import {unimplemented} from '../../facade/exceptions'; import {unimplemented} from '../../facade/exceptions';
import {ControlValueAccessor} from './control_value_accessor';
import {AbstractControlDirective} from './abstract_control_directive'; import {AbstractControlDirective} from './abstract_control_directive';
import {ControlValueAccessor} from './control_value_accessor';
import {AsyncValidatorFn, ValidatorFn} from './validators'; import {AsyncValidatorFn, ValidatorFn} from './validators';
/** /**
* A base class that all control directive extend. * A base class that all control directive extend.
* It binds a {@link Control} object to a DOM element. * It binds a {@link Control} object to a DOM element.

View File

@ -1,19 +1,11 @@
import { import {Directive, Host, Inject, OnDestroy, OnInit, Optional, Self, SkipSelf, forwardRef} from '@angular/core';
OnInit,
OnDestroy,
Directive,
Optional,
Inject,
Host,
SkipSelf,
forwardRef,
Self
} from '@angular/core';
import {ControlContainer} from './control_container';
import {controlPath, composeValidators, composeAsyncValidators} from './shared';
import {ControlGroup} from '../model'; import {ControlGroup} from '../model';
import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';
import {ControlContainer} from './control_container';
import {Form} from './form_interface'; import {Form} from './form_interface';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {composeAsyncValidators, composeValidators, controlPath} from './shared';
import {AsyncValidatorFn, ValidatorFn} from './validators'; import {AsyncValidatorFn, ValidatorFn} from './validators';
export const controlGroupProvider: any = export const controlGroupProvider: any =
@ -79,9 +71,10 @@ export class NgControlGroup extends ControlContainer implements OnInit,
/** @internal */ /** @internal */
_parent: ControlContainer; _parent: ControlContainer;
constructor(@Host() @SkipSelf() parent: ControlContainer, constructor(
@Optional() @Self() @Inject(NG_VALIDATORS) private _validators: any[], @Host() @SkipSelf() parent: ControlContainer,
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[]) { @Optional() @Self() @Inject(NG_VALIDATORS) private _validators: any[],
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[]) {
super(); super();
this._parent = parent; this._parent = parent;
} }

View File

@ -1,30 +1,14 @@
import { import {Directive, Host, Inject, OnChanges, OnDestroy, Optional, Self, SimpleChanges, SkipSelf, forwardRef} from '@angular/core';
OnChanges,
OnDestroy,
SimpleChanges,
Directive,
forwardRef,
Host,
SkipSelf,
Inject,
Optional,
Self
} from '@angular/core';
import {EventEmitter, ObservableWrapper} from '../../facade/async'; import {EventEmitter, ObservableWrapper} from '../../facade/async';
import {ControlContainer} from './control_container';
import {NgControl} from './ng_control';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {
controlPath,
composeValidators,
composeAsyncValidators,
isPropertyUpdated,
selectValueAccessor
} from './shared';
import {Control} from '../model'; import {Control} from '../model';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';
import {ValidatorFn, AsyncValidatorFn} from './validators';
import {ControlContainer} from './control_container';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {NgControl} from './ng_control';
import {composeAsyncValidators, composeValidators, controlPath, isPropertyUpdated, selectValueAccessor} from './shared';
import {AsyncValidatorFn, ValidatorFn} from './validators';
export const controlNameBinding: any = export const controlNameBinding: any =
@ -112,35 +96,37 @@ export class NgControlName extends NgControl implements OnChanges,
/* Array<Validator|Function> */ any[], /* Array<Validator|Function> */ any[],
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) @Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
valueAccessors: ControlValueAccessor[]) { valueAccessors: ControlValueAccessor[]) {
super(); super();
this.valueAccessor = selectValueAccessor(this, valueAccessors); this.valueAccessor = selectValueAccessor(this, valueAccessors);
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
if (!this._added) { if (!this._added) {
this.formDirective.addControl(this); this.formDirective.addControl(this);
this._added = true; this._added = true;
} }
if (isPropertyUpdated(changes, this.viewModel)) { if (isPropertyUpdated(changes, this.viewModel)) {
this.viewModel = this.model; this.viewModel = this.model;
this.formDirective.updateModel(this, this.model); this.formDirective.updateModel(this, this.model);
} }
} }
ngOnDestroy(): void { this.formDirective.removeControl(this); } ngOnDestroy(): void { this.formDirective.removeControl(this); }
viewToModelUpdate(newValue: any): void { viewToModelUpdate(newValue: any): void {
this.viewModel = newValue; this.viewModel = newValue;
ObservableWrapper.callEmit(this.update, newValue); ObservableWrapper.callEmit(this.update, 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.formDirective; } get formDirective(): any { return this._parent.formDirective; }
get validator(): ValidatorFn { return composeValidators(this._validators); } get validator(): ValidatorFn { return composeValidators(this._validators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); } get asyncValidator(): AsyncValidatorFn {
return composeAsyncValidators(this._asyncValidators);
}
get control(): Control { return this.formDirective.getControl(this); } get control(): Control { return this.formDirective.getControl(this); }
} }

View File

@ -1,7 +1,10 @@
import {Directive, Self} from '@angular/core'; import {Directive, Self} from '@angular/core';
import {NgControl} from './ng_control';
import {isPresent} from '../../facade/lang'; import {isPresent} from '../../facade/lang';
import {NgControl} from './ng_control';
/** /**
* Directive automatically applied to Angular forms that sets CSS classes * Directive automatically applied to Angular forms that sets CSS classes
* based on control status (valid/invalid/dirty/etc). * based on control status (valid/invalid/dirty/etc).

View File

@ -1,18 +1,16 @@
import {Directive, forwardRef, Optional, Inject, Self} from '@angular/core'; import {Directive, Inject, Optional, Self, forwardRef} from '@angular/core';
import {
PromiseWrapper, import {EventEmitter, ObservableWrapper, PromiseWrapper} from '../../facade/async';
ObservableWrapper,
EventEmitter
} from '../../facade/async';
import {ListWrapper} from '../../facade/collection'; import {ListWrapper} from '../../facade/collection';
import {isPresent} from '../../facade/lang'; import {isPresent} from '../../facade/lang';
import {NgControl} from './ng_control'; import {AbstractControl, Control, ControlGroup} from '../model';
import {Form} from './form_interface'; import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';
import {NgControlGroup} from './ng_control_group';
import {ControlContainer} from './control_container'; import {ControlContainer} from './control_container';
import {AbstractControl, ControlGroup, Control} from '../model'; import {Form} from './form_interface';
import {setUpControl, setUpControlGroup, composeValidators, composeAsyncValidators} from './shared'; import {NgControl} from './ng_control';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {NgControlGroup} from './ng_control_group';
import {composeAsyncValidators, composeValidators, setUpControl, setUpControlGroup} from './shared';
export const formDirectiveProvider: any = export const formDirectiveProvider: any =
/*@ts2dart_const*/ {provide: ControlContainer, useExisting: forwardRef(() => NgForm)}; /*@ts2dart_const*/ {provide: ControlContainer, useExisting: forwardRef(() => NgForm)};
@ -93,11 +91,12 @@ export class NgForm extends ControlContainer implements Form {
form: ControlGroup; form: ControlGroup;
ngSubmit = new EventEmitter(); ngSubmit = new EventEmitter();
constructor(@Optional() @Self() @Inject(NG_VALIDATORS) validators: any[], constructor(
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: any[]) { @Optional() @Self() @Inject(NG_VALIDATORS) validators: any[],
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: any[]) {
super(); super();
this.form = new ControlGroup({}, null, composeValidators(validators), this.form = new ControlGroup(
composeAsyncValidators(asyncValidators)); {}, null, composeValidators(validators), composeAsyncValidators(asyncValidators));
} }
get submitted(): boolean { return this._submitted; } get submitted(): boolean { return this._submitted; }

View File

@ -1,28 +1,14 @@
import { import {Directive, Inject, OnChanges, Optional, Self, SimpleChanges, forwardRef} from '@angular/core';
OnChanges,
SimpleChanges,
Directive,
forwardRef,
Inject,
Optional,
Self
} from '@angular/core';
import {StringMapWrapper} from '../../facade/collection';
import {EventEmitter, ObservableWrapper} from '../../facade/async'; import {EventEmitter, ObservableWrapper} from '../../facade/async';
import {StringMapWrapper} from '../../facade/collection';
import {NgControl} from './ng_control';
import {Control} from '../model'; import {Control} from '../model';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor'; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import { import {NgControl} from './ng_control';
setUpControl, import {composeAsyncValidators, composeValidators, isPropertyUpdated, selectValueAccessor, setUpControl} from './shared';
composeValidators, import {AsyncValidatorFn, ValidatorFn} from './validators';
composeAsyncValidators,
isPropertyUpdated,
selectValueAccessor
} from './shared';
import {ValidatorFn, AsyncValidatorFn} from './validators';
export const formControlBinding: any = export const formControlBinding: any =
/*@ts2dart_const*/ /* @ts2dart_Provider */ { /*@ts2dart_const*/ /* @ts2dart_Provider */ {
@ -98,35 +84,37 @@ export class NgFormControl extends NgControl implements OnChanges {
/* Array<Validator|Function> */ any[], /* Array<Validator|Function> */ any[],
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) @Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
valueAccessors: ControlValueAccessor[]) { valueAccessors: ControlValueAccessor[]) {
super(); super();
this.valueAccessor = selectValueAccessor(this, valueAccessors); this.valueAccessor = selectValueAccessor(this, valueAccessors);
} }
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
if (this._isControlChanged(changes)) { if (this._isControlChanged(changes)) {
setUpControl(this.form, this); setUpControl(this.form, this);
this.form.updateValueAndValidity({emitEvent: false}); this.form.updateValueAndValidity({emitEvent: false});
} }
if (isPropertyUpdated(changes, this.viewModel)) { if (isPropertyUpdated(changes, this.viewModel)) {
this.form.updateValue(this.model); this.form.updateValue(this.model);
this.viewModel = this.model; this.viewModel = this.model;
} }
} }
get path(): string[] { return []; } get path(): string[] { return []; }
get validator(): ValidatorFn { return composeValidators(this._validators); } get validator(): ValidatorFn { return composeValidators(this._validators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); } get asyncValidator(): AsyncValidatorFn {
return composeAsyncValidators(this._asyncValidators);
}
get control(): Control { return this.form; } get control(): Control { return this.form; }
viewToModelUpdate(newValue: any): void { viewToModelUpdate(newValue: any): void {
this.viewModel = newValue; this.viewModel = newValue;
ObservableWrapper.callEmit(this.update, newValue); ObservableWrapper.callEmit(this.update, newValue);
} }
private _isControlChanged(changes: {[key: string]: any}): boolean { private _isControlChanged(changes: {[key: string]: any}): boolean {
return StringMapWrapper.contains(changes, "form"); return StringMapWrapper.contains(changes, 'form');
} }
} }

View File

@ -1,23 +1,17 @@
import { import {Directive, Inject, OnChanges, Optional, Self, SimpleChanges, forwardRef} from '@angular/core';
SimpleChanges,
OnChanges, import {EventEmitter, ObservableWrapper} from '../../facade/async';
Directive,
forwardRef,
Inject,
Optional,
Self
} from '@angular/core';
import {isBlank} from '../../facade/lang';
import {ListWrapper, StringMapWrapper} from '../../facade/collection'; import {ListWrapper, StringMapWrapper} from '../../facade/collection';
import {BaseException} from '../../facade/exceptions'; import {BaseException} from '../../facade/exceptions';
import {ObservableWrapper, EventEmitter} from '../../facade/async'; import {isBlank} from '../../facade/lang';
import {NgControl} from './ng_control'; import {Control, ControlGroup} from '../model';
import {NgControlGroup} from './ng_control_group'; import {NG_ASYNC_VALIDATORS, NG_VALIDATORS, Validators} from '../validators';
import {ControlContainer} from './control_container'; import {ControlContainer} from './control_container';
import {Form} from './form_interface'; import {Form} from './form_interface';
import {Control, ControlGroup} from '../model'; import {NgControl} from './ng_control';
import {setUpControl, setUpControlGroup, composeValidators, composeAsyncValidators} from './shared'; import {NgControlGroup} from './ng_control_group';
import {Validators, NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {composeAsyncValidators, composeValidators, setUpControl, setUpControlGroup} from './shared';
export const formDirectiveProvider: any = export const formDirectiveProvider: any =
/*@ts2dart_const*/ /* @ts2dart_Provider */ { /*@ts2dart_const*/ /* @ts2dart_Provider */ {
@ -115,14 +109,15 @@ export class NgFormModel extends ControlContainer implements Form,
directives: NgControl[] = []; directives: NgControl[] = [];
ngSubmit = new EventEmitter(); ngSubmit = new EventEmitter();
constructor(@Optional() @Self() @Inject(NG_VALIDATORS) private _validators: any[], constructor(
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[]) { @Optional() @Self() @Inject(NG_VALIDATORS) private _validators: any[],
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[]) {
super(); super();
} }
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
this._checkFormPresent(); this._checkFormPresent();
if (StringMapWrapper.contains(changes, "form")) { if (StringMapWrapper.contains(changes, 'form')) {
var sync = composeValidators(this._validators); var sync = composeValidators(this._validators);
this.form.validator = Validators.compose([this.form.validator, sync]); this.form.validator = Validators.compose([this.form.validator, sync]);

View File

@ -1,25 +1,13 @@
import { import {Directive, Inject, OnChanges, Optional, Self, SimpleChanges, forwardRef} from '@angular/core';
OnChanges,
SimpleChanges,
Directive,
forwardRef,
Inject,
Optional,
Self
} from '@angular/core';
import {EventEmitter, ObservableWrapper} from '../../facade/async'; import {EventEmitter, ObservableWrapper} from '../../facade/async';
import {Control} from '../model';
import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../validators';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor'; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {NgControl} from './ng_control'; import {NgControl} from './ng_control';
import {Control} from '../model'; import {composeAsyncValidators, composeValidators, isPropertyUpdated, selectValueAccessor, setUpControl} from './shared';
import {NG_VALIDATORS, NG_ASYNC_VALIDATORS} from '../validators'; import {AsyncValidatorFn, ValidatorFn} from './validators';
import {
setUpControl,
isPropertyUpdated,
selectValueAccessor,
composeValidators,
composeAsyncValidators
} from './shared';
import {ValidatorFn, AsyncValidatorFn} from './validators';
export const formControlBinding: any = export const formControlBinding: any =
/*@ts2dart_const*/ /* @ts2dart_Provider */ { /*@ts2dart_const*/ /* @ts2dart_Provider */ {
@ -70,33 +58,35 @@ export class NgModel extends NgControl implements OnChanges {
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[], @Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[],
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) @Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
valueAccessors: ControlValueAccessor[]) { valueAccessors: ControlValueAccessor[]) {
super(); super();
this.valueAccessor = selectValueAccessor(this, valueAccessors); this.valueAccessor = selectValueAccessor(this, valueAccessors);
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
if (!this._added) { if (!this._added) {
setUpControl(this._control, this); setUpControl(this._control, this);
this._control.updateValueAndValidity({emitEvent: false}); this._control.updateValueAndValidity({emitEvent: false});
this._added = true; this._added = true;
} }
if (isPropertyUpdated(changes, this.viewModel)) { if (isPropertyUpdated(changes, this.viewModel)) {
this._control.updateValue(this.model); this._control.updateValue(this.model);
this.viewModel = this.model; this.viewModel = this.model;
} }
} }
get control(): Control { return this._control; } get control(): Control { return this._control; }
get path(): string[] { return []; } get path(): string[] { return []; }
get validator(): ValidatorFn { return composeValidators(this._validators); } get validator(): ValidatorFn { return composeValidators(this._validators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); } get asyncValidator(): AsyncValidatorFn {
return composeAsyncValidators(this._asyncValidators);
}
viewToModelUpdate(newValue: any): void { viewToModelUpdate(newValue: any): void {
this.viewModel = newValue; this.viewModel = newValue;
ObservableWrapper.callEmit(this.update, newValue); ObservableWrapper.callEmit(this.update, newValue);
} }
} }

View File

@ -1,5 +1,6 @@
import {AbstractControl} from '../model'; import {AbstractControl} from '../model';
import {Validator, ValidatorFn, AsyncValidatorFn} from './validators';
import {AsyncValidatorFn, Validator, ValidatorFn} from './validators';
export function normalizeValidator(validator: ValidatorFn | Validator): ValidatorFn { export function normalizeValidator(validator: ValidatorFn | Validator): ValidatorFn {
if ((<Validator>validator).validate !== undefined) { if ((<Validator>validator).validate !== undefined) {

View File

@ -1,6 +1,8 @@
import {Directive, ElementRef, Renderer, forwardRef} from '@angular/core'; import {Directive, ElementRef, Renderer, forwardRef} from '@angular/core';
import {NumberWrapper} from '../../facade/lang'; import {NumberWrapper} from '../../facade/lang';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from './control_value_accessor';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
export const NUMBER_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ { export const NUMBER_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

View File

@ -1,17 +1,9 @@
import { import {Directive, ElementRef, Injectable, Injector, Input, OnDestroy, OnInit, Renderer, forwardRef} from '@angular/core';
Directive,
ElementRef,
Renderer,
forwardRef,
Input,
OnInit,
OnDestroy,
Injector,
Injectable
} from '@angular/core';
import {isPresent} from '../../facade/lang';
import {ListWrapper} from '../../facade/collection'; import {ListWrapper} from '../../facade/collection';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from './control_value_accessor'; import {isPresent} from '../../facade/lang';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {NgControl} from './ng_control'; import {NgControl} from './ng_control';
export const RADIO_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ { export const RADIO_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ {
@ -49,10 +41,10 @@ export class RadioControlRegistry {
}); });
} }
private _isSameGroup(controlPair:[NgControl, RadioControlValueAccessor], private _isSameGroup(
accessor: RadioControlValueAccessor) { controlPair: [NgControl, RadioControlValueAccessor], accessor: RadioControlValueAccessor) {
return controlPair[0].control.root === accessor._control.control.root && return controlPair[0].control.root === accessor._control.control.root &&
controlPair[1].name === accessor.name; controlPair[1].name === accessor.name;
} }
} }
@ -102,8 +94,9 @@ export class RadioControlValueAccessor implements ControlValueAccessor,
onChange = () => {}; onChange = () => {};
onTouched = () => {}; onTouched = () => {};
constructor(private _renderer: Renderer, private _elementRef: ElementRef, constructor(
private _registry: RadioControlRegistry, private _injector: Injector) {} private _renderer: Renderer, private _elementRef: ElementRef,
private _registry: RadioControlRegistry, private _injector: Injector) {}
ngOnInit(): void { ngOnInit(): void {
this._control = this._injector.get(NgControl); this._control = this._injector.get(NgControl);

View File

@ -1,23 +1,9 @@
import { import {Directive, ElementRef, Host, Input, OnDestroy, Optional, Renderer, forwardRef} from '@angular/core';
Directive,
Renderer,
forwardRef,
ElementRef,
Input,
Host,
OnDestroy,
Optional
} from '@angular/core';
import {
StringWrapper,
isPrimitive,
isPresent,
isBlank,
looseIdentical
} from '../../facade/lang';
import {MapWrapper} from '../../facade/collection';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from './control_value_accessor'; import {MapWrapper} from '../../facade/collection';
import {StringWrapper, isBlank, isPresent, isPrimitive, looseIdentical} from '../../facade/lang';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
export const SELECT_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ { export const SELECT_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
@ -27,12 +13,12 @@ export const SELECT_VALUE_ACCESSOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider
function _buildValueString(id: string, value: any): string { function _buildValueString(id: string, value: any): string {
if (isBlank(id)) return `${value}`; if (isBlank(id)) return `${value}`;
if (!isPrimitive(value)) value = "Object"; if (!isPrimitive(value)) value = 'Object';
return StringWrapper.slice(`${id}: ${value}`, 0, 50); return StringWrapper.slice(`${id}: ${value}`, 0, 50);
} }
function _extractId(valueString: string): string { function _extractId(valueString: string): string {
return valueString.split(":")[0]; return valueString.split(':')[0];
} }
/** /**
@ -112,8 +98,9 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
export class NgSelectOption implements OnDestroy { export class NgSelectOption implements OnDestroy {
id: string; id: string;
constructor(private _element: ElementRef, private _renderer: Renderer, constructor(
@Optional() @Host() private _select: SelectControlValueAccessor) { private _element: ElementRef, private _renderer: Renderer,
@Optional() @Host() private _select: SelectControlValueAccessor) {
if (isPresent(this._select)) this.id = this._select._registerOption(); if (isPresent(this._select)) this.id = this._select._registerOption();
} }

View File

@ -1,23 +1,9 @@
import { import {Directive, ElementRef, Host, Input, OnDestroy, Optional, Renderer, forwardRef} from '@angular/core';
Input,
Directive,
ElementRef,
Renderer,
Optional,
Host,
OnDestroy,
forwardRef
} from "@angular/core";
import {
isBlank,
isPrimitive,
StringWrapper,
isPresent,
looseIdentical,
isString
} from '../../facade/lang';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
import {MapWrapper} from '../../facade/collection'; import {MapWrapper} from '../../facade/collection';
import {StringWrapper, isBlank, isPresent, isPrimitive, isString, looseIdentical} from '../../facade/lang';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
const SELECT_MULTIPLE_VALUE_ACCESSOR = { const SELECT_MULTIPLE_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
@ -28,12 +14,12 @@ const SELECT_MULTIPLE_VALUE_ACCESSOR = {
function _buildValueString(id: string, value: any): string { function _buildValueString(id: string, value: any): string {
if (isBlank(id)) return `${value}`; if (isBlank(id)) return `${value}`;
if (isString(value)) value = `'${value}'`; if (isString(value)) value = `'${value}'`;
if (!isPrimitive(value)) value = "Object"; if (!isPrimitive(value)) value = 'Object';
return StringWrapper.slice(`${id}: ${value}`, 0, 50); return StringWrapper.slice(`${id}: ${value}`, 0, 50);
} }
function _extractId(valueString: string): string { function _extractId(valueString: string): string {
return valueString.split(":")[0]; return valueString.split(':')[0];
} }
/** Mock interface for HTML Options */ /** Mock interface for HTML Options */
@ -74,9 +60,7 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
let values: Array<any> = <Array<any>>value; let values: Array<any> = <Array<any>>value;
// convert values to ids // convert values to ids
let ids = values.map((v) => this._getOptionId(v)); let ids = values.map((v) => this._getOptionId(v));
this._optionMap.forEach((opt, o) => { this._optionMap.forEach((opt, o) => { opt._setSelected(ids.indexOf(o.toString()) > -1); });
opt._setSelected(ids.indexOf(o.toString()) > -1);
});
} }
registerOnChange(fn: (value: any) => any): void { registerOnChange(fn: (value: any) => any): void {
@ -108,7 +92,7 @@ export class SelectMultipleControlValueAccessor implements ControlValueAccessor
/** @internal */ /** @internal */
_registerOption(value: NgSelectMultipleOption): string { _registerOption(value: NgSelectMultipleOption): string {
let id:string = (this._idCounter++).toString(); let id: string = (this._idCounter++).toString();
this._optionMap.set(id, value); this._optionMap.set(id, value);
return id; return id;
} }
@ -145,8 +129,9 @@ export class NgSelectMultipleOption implements OnDestroy {
/** @internal */ /** @internal */
_value: any; _value: any;
constructor(private _element: ElementRef, private _renderer: Renderer, constructor(
@Optional() @Host() private _select: SelectMultipleControlValueAccessor) { private _element: ElementRef, private _renderer: Renderer,
@Optional() @Host() private _select: SelectMultipleControlValueAccessor) {
if (isPresent(this._select)) { if (isPresent(this._select)) {
this.id = this._select._registerOption(this); this.id = this._select._registerOption(this);
} }

View File

@ -1,21 +1,21 @@
import {ListWrapper, StringMapWrapper} from '../../facade/collection'; import {ListWrapper, StringMapWrapper} from '../../facade/collection';
import {isBlank, isPresent, looseIdentical, hasConstructor} from '../../facade/lang';
import {BaseException} from '../../facade/exceptions'; import {BaseException} from '../../facade/exceptions';
import {hasConstructor, isBlank, isPresent, looseIdentical} from '../../facade/lang';
import {ControlContainer} from './control_container';
import {NgControl} from './ng_control';
import {AbstractControlDirective} from './abstract_control_directive';
import {NgControlGroup} from './ng_control_group';
import {Control, ControlGroup} from '../model'; import {Control, ControlGroup} from '../model';
import {Validators} from '../validators'; import {Validators} from '../validators';
import {AbstractControlDirective} from './abstract_control_directive';
import {CheckboxControlValueAccessor} from './checkbox_value_accessor';
import {ControlContainer} from './control_container';
import {ControlValueAccessor} from './control_value_accessor'; import {ControlValueAccessor} from './control_value_accessor';
import {DefaultValueAccessor} from './default_value_accessor'; import {DefaultValueAccessor} from './default_value_accessor';
import {NgControl} from './ng_control';
import {NgControlGroup} from './ng_control_group';
import {normalizeAsyncValidator, normalizeValidator} from './normalize_validator';
import {NumberValueAccessor} from './number_value_accessor'; import {NumberValueAccessor} from './number_value_accessor';
import {CheckboxControlValueAccessor} from './checkbox_value_accessor';
import {SelectControlValueAccessor} from './select_control_value_accessor';
import {RadioControlValueAccessor} from './radio_control_value_accessor'; import {RadioControlValueAccessor} from './radio_control_value_accessor';
import {normalizeValidator, normalizeAsyncValidator} from './normalize_validator'; import {SelectControlValueAccessor} from './select_control_value_accessor';
import {ValidatorFn, AsyncValidatorFn} from './validators'; import {AsyncValidatorFn, ValidatorFn} from './validators';
export function controlPath(name: string, parent: ControlContainer): string[] { export function controlPath(name: string, parent: ControlContainer): string[] {
@ -25,8 +25,8 @@ export function controlPath(name: string, parent: ControlContainer): string[] {
} }
export function setUpControl(control: Control, dir: NgControl): void { export function setUpControl(control: Control, dir: NgControl): void {
if (isBlank(control)) _throwError(dir, "Cannot find control"); if (isBlank(control)) _throwError(dir, 'Cannot find control');
if (isBlank(dir.valueAccessor)) _throwError(dir, "No value accessor for"); if (isBlank(dir.valueAccessor)) _throwError(dir, 'No value accessor for');
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]);
@ -47,13 +47,13 @@ export function setUpControl(control: Control, dir: NgControl): void {
} }
export function setUpControlGroup(control: ControlGroup, dir: NgControlGroup) { export function setUpControlGroup(control: ControlGroup, dir: NgControlGroup) {
if (isBlank(control)) _throwError(dir, "Cannot find control"); if (isBlank(control)) _throwError(dir, 'Cannot find control');
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]);
} }
function _throwError(dir: AbstractControlDirective, message: string): void { function _throwError(dir: AbstractControlDirective, message: string): void {
var path = dir.path.join(" -> "); var path = dir.path.join(' -> ');
throw new BaseException(`${message} '${path}'`); throw new BaseException(`${message} '${path}'`);
} }
@ -61,23 +61,23 @@ export function composeValidators(validators: /* Array<Validator|Function> */ an
return isPresent(validators) ? Validators.compose(validators.map(normalizeValidator)) : null; return isPresent(validators) ? Validators.compose(validators.map(normalizeValidator)) : null;
} }
export function composeAsyncValidators( export function composeAsyncValidators(validators: /* Array<Validator|Function> */ any[]):
validators: /* Array<Validator|Function> */ any[]): AsyncValidatorFn { AsyncValidatorFn {
return isPresent(validators) ? Validators.composeAsync(validators.map(normalizeAsyncValidator)) : return isPresent(validators) ? Validators.composeAsync(validators.map(normalizeAsyncValidator)) :
null; null;
} }
export function isPropertyUpdated(changes: {[key: string]: any}, viewModel: any): boolean { export function isPropertyUpdated(changes: {[key: string]: any}, viewModel: any): boolean {
if (!StringMapWrapper.contains(changes, "model")) return false; if (!StringMapWrapper.contains(changes, 'model')) return false;
var change = changes["model"]; var change = changes['model'];
if (change.isFirstChange()) return true; if (change.isFirstChange()) return true;
return !looseIdentical(viewModel, change.currentValue); return !looseIdentical(viewModel, change.currentValue);
} }
// 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(dir: NgControl, export function selectValueAccessor(
valueAccessors: ControlValueAccessor[]): ControlValueAccessor { dir: NgControl, valueAccessors: ControlValueAccessor[]): ControlValueAccessor {
if (isBlank(valueAccessors)) return null; if (isBlank(valueAccessors)) return null;
var defaultAccessor: ControlValueAccessor; var defaultAccessor: ControlValueAccessor;
@ -87,17 +87,17 @@ export function selectValueAccessor(dir: NgControl,
if (hasConstructor(v, DefaultValueAccessor)) { if (hasConstructor(v, DefaultValueAccessor)) {
defaultAccessor = v; defaultAccessor = v;
} else if (hasConstructor(v, CheckboxControlValueAccessor) || } else if (
hasConstructor(v, NumberValueAccessor) || hasConstructor(v, CheckboxControlValueAccessor) || hasConstructor(v, NumberValueAccessor) ||
hasConstructor(v, SelectControlValueAccessor) || hasConstructor(v, SelectControlValueAccessor) ||
hasConstructor(v, RadioControlValueAccessor)) { hasConstructor(v, RadioControlValueAccessor)) {
if (isPresent(builtinAccessor)) if (isPresent(builtinAccessor))
_throwError(dir, "More than one built-in value accessor matches"); _throwError(dir, 'More than one built-in value accessor matches');
builtinAccessor = v; builtinAccessor = v;
} else { } else {
if (isPresent(customAccessor)) if (isPresent(customAccessor))
_throwError(dir, "More than one custom value accessor matches"); _throwError(dir, 'More than one custom value accessor matches');
customAccessor = v; customAccessor = v;
} }
}); });
@ -106,6 +106,6 @@ export function selectValueAccessor(dir: NgControl,
if (isPresent(builtinAccessor)) return builtinAccessor; if (isPresent(builtinAccessor)) return builtinAccessor;
if (isPresent(defaultAccessor)) return defaultAccessor; if (isPresent(defaultAccessor)) return defaultAccessor;
_throwError(dir, "No valid value accessor for"); _throwError(dir, 'No valid value accessor for');
return null; return null;
} }

View File

@ -1,7 +1,8 @@
import {forwardRef, Attribute, Directive} from '@angular/core'; import {Attribute, Directive, forwardRef} from '@angular/core';
import {NumberWrapper} from '../../facade/lang'; import {NumberWrapper} from '../../facade/lang';
import {Validators, NG_VALIDATORS} from '../validators';
import {AbstractControl} from '../model'; import {AbstractControl} from '../model';
import {NG_VALIDATORS, Validators} from '../validators';
@ -82,7 +83,7 @@ export const MIN_LENGTH_VALIDATOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*
export class MinLengthValidator implements Validator { export class MinLengthValidator implements Validator {
private _validator: ValidatorFn; private _validator: ValidatorFn;
constructor(@Attribute("minlength") minLength: string) { constructor(@Attribute('minlength') minLength: string) {
this._validator = Validators.minLength(NumberWrapper.parseInt(minLength, 10)); this._validator = Validators.minLength(NumberWrapper.parseInt(minLength, 10));
} }
@ -115,7 +116,7 @@ export const MAX_LENGTH_VALIDATOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*
export class MaxLengthValidator implements Validator { export class MaxLengthValidator implements Validator {
private _validator: ValidatorFn; private _validator: ValidatorFn;
constructor(@Attribute("maxlength") maxLength: string) { constructor(@Attribute('maxlength') maxLength: string) {
this._validator = Validators.maxLength(NumberWrapper.parseInt(maxLength, 10)); this._validator = Validators.maxLength(NumberWrapper.parseInt(maxLength, 10));
} }
@ -150,7 +151,7 @@ export const PATTERN_VALIDATOR: any = /*@ts2dart_const*/ /*@ts2dart_Provider*/ {
export class PatternValidator implements Validator { export class PatternValidator implements Validator {
private _validator: ValidatorFn; private _validator: ValidatorFn;
constructor(@Attribute("pattern") pattern: string) { constructor(@Attribute('pattern') pattern: string) {
this._validator = Validators.pattern(pattern); this._validator = Validators.pattern(pattern);
} }

View File

@ -1,8 +1,11 @@
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {StringMapWrapper} from '../facade/collection'; import {StringMapWrapper} from '../facade/collection';
import {isPresent, isArray} from '../facade/lang'; import {isArray, isPresent} from '../facade/lang';
import {AsyncValidatorFn, ValidatorFn} from './directives/validators';
import * as modelModule from './model'; import * as modelModule from './model';
import {ValidatorFn, AsyncValidatorFn} from './directives/validators';
/** /**
@ -56,21 +59,21 @@ export class FormBuilder {
* *
* See the {@link ControlGroup} constructor for more details. * See the {@link ControlGroup} constructor for more details.
*/ */
group(controlsConfig: {[key: string]: any}, group(controlsConfig: {[key: string]: any}, extra: {[key: string]: any} = null):
extra: {[key: string]: any} = null): modelModule.ControlGroup { modelModule.ControlGroup {
var controls = this._reduceControls(controlsConfig); var controls = this._reduceControls(controlsConfig);
var optionals = <{[key: string]: boolean}>( var optionals = <{[key: string]: boolean}>(
isPresent(extra) ? StringMapWrapper.get(extra, "optionals") : null); isPresent(extra) ? StringMapWrapper.get(extra, 'optionals') : null);
var validator: ValidatorFn = isPresent(extra) ? StringMapWrapper.get(extra, "validator") : null; var validator: ValidatorFn = isPresent(extra) ? StringMapWrapper.get(extra, 'validator') : null;
var asyncValidator: AsyncValidatorFn = var asyncValidator: AsyncValidatorFn =
isPresent(extra) ? StringMapWrapper.get(extra, "asyncValidator") : null; isPresent(extra) ? StringMapWrapper.get(extra, 'asyncValidator') : null;
return new modelModule.ControlGroup(controls, optionals, validator, asyncValidator); return new modelModule.ControlGroup(controls, optionals, validator, asyncValidator);
} }
/** /**
* Construct a new {@link Control} with the given `value`,`validator`, and `asyncValidator`. * Construct a new {@link Control} with the given `value`,`validator`, and `asyncValidator`.
*/ */
control(value: Object, validator: ValidatorFn = null, control(value: Object, validator: ValidatorFn = null, asyncValidator: AsyncValidatorFn = null):
asyncValidator: AsyncValidatorFn = null): modelModule.Control { modelModule.Control {
return new modelModule.Control(value, validator, asyncValidator); return new modelModule.Control(value, validator, asyncValidator);
} }
@ -78,15 +81,16 @@ export class FormBuilder {
* Construct an array of {@link Control}s from the given `controlsConfig` array of * Construct an array of {@link Control}s from the given `controlsConfig` array of
* configuration, with the given optional `validator` and `asyncValidator`. * configuration, with the given optional `validator` and `asyncValidator`.
*/ */
array(controlsConfig: any[], validator: ValidatorFn = null, array(
asyncValidator: AsyncValidatorFn = null): modelModule.ControlArray { controlsConfig: any[], validator: ValidatorFn = null,
asyncValidator: AsyncValidatorFn = null): modelModule.ControlArray {
var controls = controlsConfig.map(c => this._createControl(c)); var controls = controlsConfig.map(c => this._createControl(c));
return new modelModule.ControlArray(controls, validator, asyncValidator); return new modelModule.ControlArray(controls, validator, asyncValidator);
} }
/** @internal */ /** @internal */
_reduceControls(controlsConfig: {[k: string]: _reduceControls(controlsConfig: {[k: string]: any}):
any}): {[key: string]: modelModule.AbstractControl} { {[key: string]: modelModule.AbstractControl} {
var controls: {[key: string]: modelModule.AbstractControl} = {}; var controls: {[key: string]: modelModule.AbstractControl} = {};
StringMapWrapper.forEach(controlsConfig, (controlConfig: any, controlName: string) => { StringMapWrapper.forEach(controlsConfig, (controlConfig: any, controlName: string) => {
controls[controlName] = this._createControl(controlConfig); controls[controlName] = this._createControl(controlConfig);

View File

@ -1,48 +1,49 @@
import {isPresent, isBlank, normalizeBool} from '../facade/lang'; import {EventEmitter, Observable, ObservableWrapper} from '../facade/async';
import {Observable, EventEmitter, ObservableWrapper} from '../facade/async'; import {ListWrapper, StringMapWrapper} from '../facade/collection';
import {isBlank, isPresent, normalizeBool} from '../facade/lang';
import {PromiseWrapper} from '../facade/promise'; import {PromiseWrapper} from '../facade/promise';
import {StringMapWrapper, ListWrapper} from '../facade/collection';
import {ValidatorFn, AsyncValidatorFn} from './directives/validators'; import {AsyncValidatorFn, ValidatorFn} from './directives/validators';
/** /**
* Indicates that a Control is valid, i.e. that no errors exist in the input value. * Indicates that a Control is valid, i.e. that no errors exist in the input value.
*/ */
export const VALID = "VALID"; export const VALID = 'VALID';
/** /**
* Indicates that a Control is invalid, i.e. that an error exists in the input value. * Indicates that a Control is invalid, i.e. that an error exists in the input value.
*/ */
export const INVALID = "INVALID"; export const INVALID = 'INVALID';
/** /**
* Indicates that a Control is pending, i.e. that async validation is occurring and * Indicates that a Control is pending, i.e. that async validation is occurring and
* errors are not yet available for the input value. * errors are not yet available for the input value.
*/ */
export const PENDING = "PENDING"; export const PENDING = 'PENDING';
export function isControl(control: Object): boolean { export function isControl(control: Object): boolean {
return control instanceof AbstractControl; return control instanceof AbstractControl;
} }
function _find(control: AbstractControl, path: Array<string | number>| string) { function _find(control: AbstractControl, path: Array<string|number>| string) {
if (isBlank(path)) return null; if (isBlank(path)) return null;
if (!(path instanceof Array)) { if (!(path instanceof Array)) {
path = (<string>path).split("/"); path = (<string>path).split('/');
} }
if (path instanceof Array && ListWrapper.isEmpty(path)) return null; if (path instanceof Array && ListWrapper.isEmpty(path)) return null;
return (<Array<string | number>>path) return (<Array<string|number>>path).reduce((v, name) => {
.reduce((v, name) => { if (v instanceof ControlGroup) {
if (v instanceof ControlGroup) { return isPresent(v.controls[name]) ? v.controls[name] : null;
return isPresent(v.controls[name]) ? v.controls[name] : null; } else if (v instanceof ControlArray) {
} else if (v instanceof ControlArray) { var index = <number>name;
var index = <number>name; return isPresent(v.at(index)) ? v.at(index) : null;
return isPresent(v.at(index)) ? v.at(index) : null; } else {
} else { return null;
return null; }
} }, control);
}, control);
} }
function toObservable(r: any): Observable<any> { function toObservable(r: any): Observable<any> {
@ -62,7 +63,7 @@ export abstract class AbstractControl {
private _errors: {[key: string]: any}; private _errors: {[key: string]: any};
private _pristine: boolean = true; private _pristine: boolean = true;
private _touched: boolean = false; private _touched: boolean = false;
private _parent: ControlGroup | ControlArray; private _parent: ControlGroup|ControlArray;
private _asyncValidationSubscription: any; private _asyncValidationSubscription: any;
constructor(public validator: ValidatorFn, public asyncValidator: AsyncValidatorFn) {} constructor(public validator: ValidatorFn, public asyncValidator: AsyncValidatorFn) {}
@ -112,10 +113,10 @@ export abstract class AbstractControl {
} }
} }
setParent(parent: ControlGroup | ControlArray): void { this._parent = parent; } setParent(parent: ControlGroup|ControlArray): void { this._parent = parent; }
updateValueAndValidity( updateValueAndValidity({onlySelf, emitEvent}: {onlySelf?: boolean, emitEvent?: boolean} = {}):
{onlySelf, emitEvent}: {onlySelf?: boolean, emitEvent?: boolean} = {}): void { void {
onlySelf = normalizeBool(onlySelf); onlySelf = normalizeBool(onlySelf);
emitEvent = isPresent(emitEvent) ? emitEvent : true; emitEvent = isPresent(emitEvent) ? emitEvent : true;
@ -196,7 +197,7 @@ export abstract class AbstractControl {
} }
} }
find(path: Array<string | number>| string): AbstractControl { return _find(this, path); } find(path: Array<string|number>|string): AbstractControl { return _find(this, path); }
getError(errorCode: string, path: string[] = null): any { getError(errorCode: string, path: string[] = null): any {
var control = isPresent(path) && !ListWrapper.isEmpty(path) ? this.find(path) : this; var control = isPresent(path) && !ListWrapper.isEmpty(path) ? this.find(path) : this;
@ -273,8 +274,8 @@ export class Control extends AbstractControl {
/** @internal */ /** @internal */
_onChange: Function; _onChange: Function;
constructor(value: any = null, validator: ValidatorFn = null, constructor(
asyncValidator: AsyncValidatorFn = null) { value: any = null, validator: ValidatorFn = null, asyncValidator: AsyncValidatorFn = null) {
super(validator, asyncValidator); super(validator, asyncValidator);
this._value = value; this._value = value;
this.updateValueAndValidity({onlySelf: true, emitEvent: false}); this.updateValueAndValidity({onlySelf: true, emitEvent: false});
@ -339,9 +340,9 @@ export class Control extends AbstractControl {
export class ControlGroup extends AbstractControl { export class ControlGroup extends AbstractControl {
private _optionals: {[key: string]: boolean}; private _optionals: {[key: string]: boolean};
constructor(public controls: {[key: string]: AbstractControl}, constructor(
optionals: {[key: string]: boolean} = null, validator: ValidatorFn = null, public controls: {[key: string]: AbstractControl}, optionals: {[key: string]: boolean} = null,
asyncValidator: AsyncValidatorFn = null) { validator: ValidatorFn = null, asyncValidator: AsyncValidatorFn = null) {
super(validator, asyncValidator); super(validator, asyncValidator);
this._optionals = isPresent(optionals) ? optionals : {}; this._optionals = isPresent(optionals) ? optionals : {};
this._initObservables(); this._initObservables();
@ -467,8 +468,9 @@ export class ControlGroup extends AbstractControl {
* @experimental * @experimental
*/ */
export class ControlArray extends AbstractControl { export class ControlArray extends AbstractControl {
constructor(public controls: AbstractControl[], validator: ValidatorFn = null, constructor(
asyncValidator: AsyncValidatorFn = null) { public controls: AbstractControl[], validator: ValidatorFn = null,
asyncValidator: AsyncValidatorFn = null) {
super(validator, asyncValidator); super(validator, asyncValidator);
this._initObservables(); this._initObservables();
this._setParentForControls(); this._setParentForControls();

View File

@ -1,10 +1,13 @@
import {OpaqueToken} from '@angular/core'; import {OpaqueToken} from '@angular/core';
import {isBlank, isPresent, isString} from '../facade/lang';
import {PromiseWrapper} from '../facade/promise';
import {ObservableWrapper} from '../facade/async'; import {ObservableWrapper} from '../facade/async';
import {StringMapWrapper} from '../facade/collection'; import {StringMapWrapper} from '../facade/collection';
import {isBlank, isPresent, isString} from '../facade/lang';
import {PromiseWrapper} from '../facade/promise';
import {AsyncValidatorFn, ValidatorFn} from './directives/validators';
import * as modelModule from './model'; import * as modelModule from './model';
import {ValidatorFn, AsyncValidatorFn} from './directives/validators';
/** /**
* Providers for validators to be used for {@link Control}s in a form. * Providers for validators to be used for {@link Control}s in a form.
@ -16,7 +19,7 @@ import {ValidatorFn, AsyncValidatorFn} from './directives/validators';
* {@example core/forms/ts/ng_validators/ng_validators.ts region='ng_validators'} * {@example core/forms/ts/ng_validators/ng_validators.ts region='ng_validators'}
* @experimental * @experimental
*/ */
export const NG_VALIDATORS: OpaqueToken = /*@ts2dart_const*/ new OpaqueToken("NgValidators"); export const NG_VALIDATORS: OpaqueToken = /*@ts2dart_const*/ new OpaqueToken('NgValidators');
/** /**
* Providers for asynchronous validators to be used for {@link Control}s * Providers for asynchronous validators to be used for {@link Control}s
@ -29,7 +32,7 @@ export const NG_VALIDATORS: OpaqueToken = /*@ts2dart_const*/ new OpaqueToken("Ng
* @experimental * @experimental
*/ */
export const NG_ASYNC_VALIDATORS: OpaqueToken = export const NG_ASYNC_VALIDATORS: OpaqueToken =
/*@ts2dart_const*/ new OpaqueToken("NgAsyncValidators"); /*@ts2dart_const*/ new OpaqueToken('NgAsyncValidators');
/** /**
* Provides a set of validators used by form controls. * Provides a set of validators used by form controls.
@ -50,9 +53,9 @@ export class Validators {
* Validator that requires controls to have a non-empty value. * Validator that requires controls to have a non-empty value.
*/ */
static required(control: modelModule.AbstractControl): {[key: string]: boolean} { static required(control: modelModule.AbstractControl): {[key: string]: boolean} {
return isBlank(control.value) || (isString(control.value) && control.value == "") ? return isBlank(control.value) || (isString(control.value) && control.value == '') ?
{"required": true} : {'required': true} :
null; null;
} }
/** /**
@ -63,8 +66,8 @@ export class Validators {
if (isPresent(Validators.required(control))) return null; if (isPresent(Validators.required(control))) return null;
var v: string = control.value; var v: string = control.value;
return v.length < minLength ? return v.length < minLength ?
{"minlength": {"requiredLength": minLength, "actualLength": v.length}} : {'minlength': {'requiredLength': minLength, 'actualLength': v.length}} :
null; null;
}; };
} }
@ -76,8 +79,8 @@ export class Validators {
if (isPresent(Validators.required(control))) return null; if (isPresent(Validators.required(control))) return null;
var v: string = control.value; var v: string = control.value;
return v.length > maxLength ? return v.length > maxLength ?
{"maxlength": {"requiredLength": maxLength, "actualLength": v.length}} : {'maxlength': {'requiredLength': maxLength, 'actualLength': v.length}} :
null; null;
}; };
} }
@ -90,7 +93,7 @@ export class Validators {
let regex = new RegExp(`^${pattern}$`); let regex = new RegExp(`^${pattern}$`);
let v: string = control.value; let v: string = control.value;
return regex.test(v) ? null : return regex.test(v) ? null :
{"pattern": {"requiredPattern": `^${pattern}$`, "actualValue": v}}; {'pattern': {'requiredPattern': `^${pattern}$`, 'actualValue': v}};
}; };
} }
@ -129,13 +132,13 @@ function _convertToPromise(obj: any): any {
return PromiseWrapper.isPromise(obj) ? obj : ObservableWrapper.toPromise(obj); return PromiseWrapper.isPromise(obj) ? obj : ObservableWrapper.toPromise(obj);
} }
function _executeValidators(control: modelModule.AbstractControl, function _executeValidators(
validators: ValidatorFn[]): any[] { control: modelModule.AbstractControl, validators: ValidatorFn[]): any[] {
return validators.map(v => v(control)); return validators.map(v => v(control));
} }
function _executeAsyncValidators(control: modelModule.AbstractControl, function _executeAsyncValidators(
validators: AsyncValidatorFn[]): any[] { control: modelModule.AbstractControl, validators: AsyncValidatorFn[]): any[] {
return validators.map(v => v(control)); return validators.map(v => v(control));
} }

View File

@ -1,9 +1,11 @@
import {Injectable, Inject, Optional} from '@angular/core'; import {Inject, Injectable, Optional} from '@angular/core';
import {isPresent} from '../facade/lang'; import {isPresent} from '../facade/lang';
import {LocationStrategy, APP_BASE_HREF} from './location_strategy';
import {Location} from './location'; import {Location} from './location';
import {UrlChangeListener, PlatformLocation} from './platform_location'; import {APP_BASE_HREF, LocationStrategy} from './location_strategy';
import {PlatformLocation, UrlChangeListener} from './platform_location';
/** /**
@ -51,8 +53,9 @@ import {UrlChangeListener, PlatformLocation} from './platform_location';
@Injectable() @Injectable()
export class HashLocationStrategy extends LocationStrategy { export class HashLocationStrategy extends LocationStrategy {
private _baseHref: string = ''; private _baseHref: string = '';
constructor(private _platformLocation: PlatformLocation, constructor(
@Optional() @Inject(APP_BASE_HREF) _baseHref?: string) { private _platformLocation: PlatformLocation,
@Optional() @Inject(APP_BASE_HREF) _baseHref?: string) {
super(); super();
if (isPresent(_baseHref)) { if (isPresent(_baseHref)) {
this._baseHref = _baseHref; this._baseHref = _baseHref;

View File

@ -1,8 +1,10 @@
import {Injectable, EventEmitter} from '@angular/core'; import {EventEmitter, Injectable} from '@angular/core';
import {ObservableWrapper} from '../facade/async'; import {ObservableWrapper} from '../facade/async';
import {LocationStrategy} from './location_strategy'; import {LocationStrategy} from './location_strategy';
/** /**
* `Location` is a service that applications can use to interact with a browser's URL. * `Location` is a service that applications can use to interact with a browser's URL.
* Depending on which {@link LocationStrategy} is used, `Location` will either persist * Depending on which {@link LocationStrategy} is used, `Location` will either persist
@ -127,8 +129,9 @@ export class Location {
/** /**
* Subscribe to the platform's `popState` events. * Subscribe to the platform's `popState` events.
*/ */
subscribe(onNext: (value: any) => void, onThrow: (exception: any) => void = null, subscribe(
onReturn: () => void = null): Object { onNext: (value: any) => void, onThrow: (exception: any) => void = null,
onReturn: () => void = null): Object {
return ObservableWrapper.subscribe(this._subject, onNext, onThrow, onReturn); return ObservableWrapper.subscribe(this._subject, onNext, onThrow, onReturn);
} }

View File

@ -1,10 +1,12 @@
import {Injectable, Inject, Optional} from '@angular/core'; import {Inject, Injectable, Optional} from '@angular/core';
import {isBlank} from '../facade/lang';
import {BaseException} from '../facade/exceptions'; import {BaseException} from '../facade/exceptions';
import {isBlank} from '../facade/lang';
import {PlatformLocation, UrlChangeListener} from './platform_location';
import {LocationStrategy, APP_BASE_HREF} from './location_strategy';
import {Location} from './location'; import {Location} from './location';
import {APP_BASE_HREF, LocationStrategy} from './location_strategy';
import {PlatformLocation, UrlChangeListener} from './platform_location';
/** /**
* `PathLocationStrategy` is a {@link LocationStrategy} used to configure the * `PathLocationStrategy` is a {@link LocationStrategy} used to configure the
@ -60,8 +62,9 @@ import {Location} from './location';
export class PathLocationStrategy extends LocationStrategy { export class PathLocationStrategy extends LocationStrategy {
private _baseHref: string; private _baseHref: string;
constructor(private _platformLocation: PlatformLocation, constructor(
@Optional() @Inject(APP_BASE_HREF) href?: string) { private _platformLocation: PlatformLocation,
@Optional() @Inject(APP_BASE_HREF) href?: string) {
super(); super();
if (isBlank(href)) { if (isBlank(href)) {
@ -89,7 +92,7 @@ export class PathLocationStrategy extends LocationStrategy {
path(): string { path(): string {
return this._platformLocation.pathname + return this._platformLocation.pathname +
Location.normalizeQueryParams(this._platformLocation.search); Location.normalizeQueryParams(this._platformLocation.search);
} }
pushState(state: any, title: string, url: string, queryParams: string) { pushState(state: any, title: string, url: string, queryParams: string) {

View File

@ -5,13 +5,13 @@
*/ */
export {AsyncPipe} from './pipes/async_pipe'; export {AsyncPipe} from './pipes/async_pipe';
export {COMMON_PIPES} from './pipes/common_pipes';
export {DatePipe} from './pipes/date_pipe'; export {DatePipe} from './pipes/date_pipe';
export {JsonPipe} from './pipes/json_pipe';
export {SlicePipe} from './pipes/slice_pipe';
export {LowerCasePipe} from './pipes/lowercase_pipe';
export {DecimalPipe, PercentPipe, CurrencyPipe} from './pipes/number_pipe';
export {UpperCasePipe} from './pipes/uppercase_pipe';
export {ReplacePipe} from './pipes/replace_pipe';
export {I18nPluralPipe} from './pipes/i18n_plural_pipe'; export {I18nPluralPipe} from './pipes/i18n_plural_pipe';
export {I18nSelectPipe} from './pipes/i18n_select_pipe'; export {I18nSelectPipe} from './pipes/i18n_select_pipe';
export {COMMON_PIPES} from './pipes/common_pipes'; export {JsonPipe} from './pipes/json_pipe';
export {LowerCasePipe} from './pipes/lowercase_pipe';
export {CurrencyPipe, DecimalPipe, PercentPipe} from './pipes/number_pipe';
export {ReplacePipe} from './pipes/replace_pipe';
export {SlicePipe} from './pipes/slice_pipe';
export {UpperCasePipe} from './pipes/uppercase_pipe';

View File

@ -1,7 +1,7 @@
import {Pipe, Injectable, ChangeDetectorRef, OnDestroy, WrappedValue} from '@angular/core'; import {ChangeDetectorRef, Injectable, OnDestroy, Pipe, WrappedValue} from '@angular/core';
import {EventEmitter, Observable, ObservableWrapper} from '../facade/async';
import {isBlank, isPresent, isPromise} from '../facade/lang'; import {isBlank, isPresent, isPromise} from '../facade/lang';
import {ObservableWrapper, Observable, EventEmitter} from '../facade/async';
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception'; import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
@ -13,7 +13,7 @@ interface SubscriptionStrategy {
class ObservableStrategy implements SubscriptionStrategy { class ObservableStrategy implements SubscriptionStrategy {
createSubscription(async: any, updateLatestValue: any): any { createSubscription(async: any, updateLatestValue: any): any {
return ObservableWrapper.subscribe(async, updateLatestValue, e => { throw e; } ); return ObservableWrapper.subscribe(async, updateLatestValue, e => { throw e; });
} }
dispose(subscription: any): void { ObservableWrapper.dispose(subscription); } dispose(subscription: any): void { ObservableWrapper.dispose(subscription); }
@ -73,7 +73,7 @@ export class AsyncPipe implements OnDestroy {
/** @internal */ /** @internal */
_subscription: Object = null; _subscription: Object = null;
/** @internal */ /** @internal */
_obj: Observable<any>| Promise<any>| EventEmitter<any> = null; _obj: Observable<any>|Promise<any>|EventEmitter<any> = null;
/** @internal */ /** @internal */
_ref: ChangeDetectorRef; _ref: ChangeDetectorRef;
private _strategy: SubscriptionStrategy = null; private _strategy: SubscriptionStrategy = null;
@ -86,7 +86,7 @@ export class AsyncPipe implements OnDestroy {
} }
} }
transform(obj: Observable<any>| Promise<any>| EventEmitter<any>): any { transform(obj: Observable<any>|Promise<any>|EventEmitter<any>): any {
if (isBlank(this._obj)) { if (isBlank(this._obj)) {
if (isPresent(obj)) { if (isPresent(obj)) {
this._subscribe(obj); this._subscribe(obj);
@ -109,7 +109,7 @@ export class AsyncPipe implements OnDestroy {
} }
/** @internal */ /** @internal */
_subscribe(obj: Observable<any>| Promise<any>| EventEmitter<any>): void { _subscribe(obj: Observable<any>|Promise<any>|EventEmitter<any>): void {
this._obj = obj; this._obj = obj;
this._strategy = this._selectStrategy(obj); this._strategy = this._selectStrategy(obj);
this._subscription = this._strategy.createSubscription( this._subscription = this._strategy.createSubscription(
@ -117,7 +117,7 @@ export class AsyncPipe implements OnDestroy {
} }
/** @internal */ /** @internal */
_selectStrategy(obj: Observable<any>| Promise<any>| EventEmitter<any>): any { _selectStrategy(obj: Observable<any>|Promise<any>|EventEmitter<any>): any {
if (isPromise(obj)) { if (isPromise(obj)) {
return _promiseStrategy; return _promiseStrategy;
} else if (ObservableWrapper.isObservable(obj)) { } else if (ObservableWrapper.isObservable(obj)) {

View File

@ -4,15 +4,16 @@
* This module provides a set of common Pipes. * This module provides a set of common Pipes.
*/ */
import {AsyncPipe} from './async_pipe'; import {AsyncPipe} from './async_pipe';
import {UpperCasePipe} from './uppercase_pipe';
import {LowerCasePipe} from './lowercase_pipe';
import {JsonPipe} from './json_pipe';
import {SlicePipe} from './slice_pipe';
import {DatePipe} from './date_pipe'; import {DatePipe} from './date_pipe';
import {DecimalPipe, PercentPipe, CurrencyPipe} from './number_pipe';
import {ReplacePipe} from './replace_pipe';
import {I18nPluralPipe} from './i18n_plural_pipe'; import {I18nPluralPipe} from './i18n_plural_pipe';
import {I18nSelectPipe} from './i18n_select_pipe'; import {I18nSelectPipe} from './i18n_select_pipe';
import {JsonPipe} from './json_pipe';
import {LowerCasePipe} from './lowercase_pipe';
import {CurrencyPipe, DecimalPipe, PercentPipe} from './number_pipe';
import {ReplacePipe} from './replace_pipe';
import {SlicePipe} from './slice_pipe';
import {UpperCasePipe} from './uppercase_pipe';
/** /**
* A collection of Angular core pipes that are likely to be used in each and every * A collection of Angular core pipes that are likely to be used in each and every
@ -35,5 +36,5 @@ export const COMMON_PIPES = /*@ts2dart_const*/[
DatePipe, DatePipe,
ReplacePipe, ReplacePipe,
I18nPluralPipe, I18nPluralPipe,
I18nSelectPipe I18nSelectPipe,
]; ];

View File

@ -1,11 +1,6 @@
import {PipeTransform, Pipe, Injectable} from '@angular/core'; import {Injectable, Pipe, PipeTransform} from '@angular/core';
import {
isDate, import {isDate, isNumber, isString, DateWrapper, isBlank,} from '../facade/lang';
isNumber,
isString,
DateWrapper,
isBlank,
} from '../facade/lang';
import {DateFormatter} from '../facade/intl'; import {DateFormatter} from '../facade/intl';
import {StringMapWrapper} from '../facade/collection'; import {StringMapWrapper} from '../facade/collection';

View File

@ -1,5 +1,7 @@
import {PipeTransform, Pipe} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
import {isStringMap, StringWrapper, isPresent, RegExpWrapper} from '../facade/lang';
import {RegExpWrapper, StringWrapper, isPresent, isStringMap} from '../facade/lang';
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception'; import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
var interpolationExp: RegExp = RegExpWrapper.create('#'); var interpolationExp: RegExp = RegExpWrapper.create('#');

View File

@ -1,8 +1,11 @@
import {PipeTransform, Pipe} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
import {isStringMap} from '../facade/lang';
import {StringMapWrapper} from '../facade/collection'; import {StringMapWrapper} from '../facade/collection';
import {isStringMap} from '../facade/lang';
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception'; import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
/** /**
* *
* Generic selector that displays the string that matches the current value. * Generic selector that displays the string that matches the current value.

View File

@ -1,5 +1,5 @@
import {Type, stringify} from '../facade/lang';
import {BaseException} from '../facade/exceptions'; import {BaseException} from '../facade/exceptions';
import {Type, stringify} from '../facade/lang';
export class InvalidPipeArgumentException extends BaseException { export class InvalidPipeArgumentException extends BaseException {
constructor(type: Type, value: Object) { constructor(type: Type, value: Object) {

View File

@ -1,7 +1,9 @@
import {PipeTransform, Pipe} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
import {Json} from '../facade/lang'; import {Json} from '../facade/lang';
/** /**
* Transforms any input value using `JSON.stringify`. Useful for debugging. * Transforms any input value using `JSON.stringify`. Useful for debugging.
* *

View File

@ -1,7 +1,10 @@
import {PipeTransform, Pipe} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
import {isString, isBlank} from '../facade/lang';
import {isBlank, isString} from '../facade/lang';
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception'; import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
/** /**
* Transforms text to lowercase. * Transforms text to lowercase.
* *

View File

@ -1,15 +1,8 @@
import {PipeTransform, Pipe} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
import {
isNumber,
isPresent,
isBlank,
NumberWrapper,
RegExpWrapper,
Type
} from '../facade/lang';
import {BaseException} from '../facade/exceptions'; import {BaseException} from '../facade/exceptions';
import {NumberFormatter, NumberFormatStyle} from '../facade/intl'; import {NumberFormatStyle, NumberFormatter} from '../facade/intl';
import {NumberWrapper, RegExpWrapper, Type, isBlank, isNumber, isPresent} from '../facade/lang';
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception'; import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
@ -19,8 +12,9 @@ var _re = RegExpWrapper.create('^(\\d+)?\\.((\\d+)(\\-(\\d+))?)?$');
/** /**
* Internal function to format numbers used by Decimal, Percent and Date pipes. * Internal function to format numbers used by Decimal, Percent and Date pipes.
*/ */
function formatNumber(pipe: Type, value: number, style: NumberFormatStyle, digits: string, currency: string = null, function formatNumber(
currencyAsSymbol: boolean = false): string { pipe: Type, value: number, style: NumberFormatStyle, digits: string, currency: string = null,
currencyAsSymbol: boolean = false): string {
if (isBlank(value)) return null; if (isBlank(value)) return null;
if (!isNumber(value)) { if (!isNumber(value)) {
throw new InvalidPipeArgumentException(pipe, value); throw new InvalidPipeArgumentException(pipe, value);
@ -138,9 +132,10 @@ export class PercentPipe implements PipeTransform {
*/ */
@Pipe({name: 'currency'}) @Pipe({name: 'currency'})
export class CurrencyPipe implements PipeTransform { export class CurrencyPipe implements PipeTransform {
transform(value: any, currencyCode: string = 'USD', symbolDisplay: boolean = false, transform(
digits: string = null): string { value: any, currencyCode: string = 'USD', symbolDisplay: boolean = false,
return formatNumber(CurrencyPipe, value, NumberFormatStyle.Currency, digits, currencyCode, digits: string = null): string {
symbolDisplay); return formatNumber(
CurrencyPipe, value, NumberFormatStyle.Currency, digits, currencyCode, symbolDisplay);
} }
} }

View File

@ -1,13 +1,6 @@
import {Injectable, PipeTransform, Pipe} from '@angular/core'; import {Injectable, Pipe, PipeTransform} from '@angular/core';
import { import {RegExpWrapper, StringWrapper, isBlank, isFunction, isNumber, isString} from '../facade/lang';
isBlank,
isString,
isNumber,
isFunction,
RegExpWrapper,
StringWrapper
} from '../facade/lang';
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception'; import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
@ -44,7 +37,7 @@ import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
@Pipe({name: 'replace'}) @Pipe({name: 'replace'})
@Injectable() @Injectable()
export class ReplacePipe implements PipeTransform { export class ReplacePipe implements PipeTransform {
transform(value: any, pattern: string | RegExp, replacement: Function | string): any { transform(value: any, pattern: string|RegExp, replacement: Function|string): any {
if (isBlank(value)) { if (isBlank(value)) {
return value; return value;
} }

View File

@ -1,6 +1,7 @@
import {PipeTransform, Pipe} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
import {isBlank, isString, isArray, StringWrapper} from '../facade/lang';
import {ListWrapper} from '../facade/collection'; import {ListWrapper} from '../facade/collection';
import {StringWrapper, isArray, isBlank, isString} from '../facade/lang';
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception'; import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';

View File

@ -1,7 +1,10 @@
import {PipeTransform, Pipe} from '@angular/core'; import {Pipe, PipeTransform} from '@angular/core';
import {isString, isBlank} from '../facade/lang';
import {isBlank, isString} from '../facade/lang';
import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception'; import {InvalidPipeArgumentException} from './invalid_pipe_argument_exception';
/** /**
* Implements uppercase transforms to text. * Implements uppercase transforms to text.
* *

View File

@ -1,15 +1,4 @@
import { import {beforeEach, beforeEachProviders, ddescribe, xdescribe, describe, expect, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
beforeEach,
beforeEachProviders,
ddescribe,
xdescribe,
describe,
expect,
iit,
inject,
it,
xit,
} from '@angular/core/testing/testing_internal';
import {ComponentFixture, TestComponentBuilder} from '@angular/compiler/testing'; import {ComponentFixture, TestComponentBuilder} from '@angular/compiler/testing';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {ListWrapper, StringMapWrapper, SetWrapper} from '../../src/facade/collection'; import {ListWrapper, StringMapWrapper, SetWrapper} from '../../src/facade/collection';
@ -25,499 +14,564 @@ export function main() {
describe('binding to CSS class list', () => { describe('binding to CSS class list', () => {
it('should clean up when the directive is destroyed', it('should clean up when the directive is destroyed',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div *ngFor="let item of items" [ngClass]="item"></div>'; [TestComponentBuilder, AsyncTestCompleter],
tcb.overrideTemplate(TestComponent, template) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.createAsync(TestComponent) var template = '<div *ngFor="let item of items" [ngClass]="item"></div>';
.then((fixture) => { tcb.overrideTemplate(TestComponent, template)
fixture.debugElement.componentInstance.items = [['0']]; .createAsync(TestComponent)
fixture.detectChanges(); .then((fixture) => {
fixture.debugElement.componentInstance.items = [['1']]; fixture.debugElement.componentInstance.items = [['0']];
fixture.detectChanges();
fixture.debugElement.componentInstance.items = [['1']];
detectChangesAndCheck(fixture, '1'); detectChangesAndCheck(fixture, '1');
async.done(); async.done();
}); });
})); }));
describe('expressions evaluating to objects', () => { describe('expressions evaluating to objects', () => {
it('should add classes specified in an object literal', it('should add classes specified in an object literal',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="{foo: true, bar: false}"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="{foo: true, bar: false}"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
async.done(); async.done();
}); });
})); }));
it('should add classes specified in an object literal without change in class names', it('should add classes specified in an object literal without change in class names',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div [ngClass]="{'foo-bar': true, 'fooBar': true}"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div [ngClass]="{'foo-bar': true, 'fooBar': true}"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo-bar fooBar'); detectChangesAndCheck(fixture, 'foo-bar fooBar');
async.done(); async.done();
}); });
})); }));
it('should add and remove classes based on changes in object literal values', it('should add and remove classes based on changes in object literal values',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="{foo: condition, bar: !condition}"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="{foo: condition, bar: !condition}"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.condition = false; fixture.debugElement.componentInstance.condition = false;
detectChangesAndCheck(fixture, 'bar'); detectChangesAndCheck(fixture, 'bar');
async.done(); async.done();
}); });
})); }));
it('should add and remove classes based on changes to the expression object', it('should add and remove classes based on changes to the expression object',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="objExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="objExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true); StringMapWrapper.set(
detectChangesAndCheck(fixture, 'foo bar'); fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, 'foo bar');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'baz', true); StringMapWrapper.set(
detectChangesAndCheck(fixture, 'foo bar baz'); fixture.debugElement.componentInstance.objExpr, 'baz', true);
detectChangesAndCheck(fixture, 'foo bar baz');
StringMapWrapper.delete(fixture.debugElement.componentInstance.objExpr, 'bar'); StringMapWrapper.delete(fixture.debugElement.componentInstance.objExpr, 'bar');
detectChangesAndCheck(fixture, 'foo baz'); detectChangesAndCheck(fixture, 'foo baz');
async.done(); async.done();
}); });
})); }));
it('should add and remove classes based on reference changes to the expression object', it('should add and remove classes based on reference changes to the expression object',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="objExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="objExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.objExpr = {foo: true, bar: true}; fixture.debugElement.componentInstance.objExpr = {foo: true, bar: true};
detectChangesAndCheck(fixture, 'foo bar'); detectChangesAndCheck(fixture, 'foo bar');
fixture.debugElement.componentInstance.objExpr = {baz: true}; fixture.debugElement.componentInstance.objExpr = {baz: true};
detectChangesAndCheck(fixture, 'baz'); detectChangesAndCheck(fixture, 'baz');
async.done(); async.done();
}); });
})); }));
it('should remove active classes when expression evaluates to null', it('should remove active classes when expression evaluates to null',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="objExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="objExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.objExpr = null; fixture.debugElement.componentInstance.objExpr = null;
detectChangesAndCheck(fixture, ''); detectChangesAndCheck(fixture, '');
fixture.debugElement.componentInstance.objExpr = {'foo': false, 'bar': true}; fixture.debugElement.componentInstance.objExpr = {'foo': false, 'bar': true};
detectChangesAndCheck(fixture, 'bar'); detectChangesAndCheck(fixture, 'bar');
async.done(); async.done();
}); });
})); }));
it('should allow multiple classes per expression', it('should allow multiple classes per expression',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="objExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="objExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.objExpr = { fixture.debugElement.componentInstance.objExpr = {
'bar baz': true, 'bar baz': true,
'bar1 baz1': true 'bar1 baz1': true
}; };
detectChangesAndCheck(fixture, 'bar baz bar1 baz1'); detectChangesAndCheck(fixture, 'bar baz bar1 baz1');
fixture.debugElement.componentInstance.objExpr = { fixture.debugElement.componentInstance.objExpr = {
'bar baz': false, 'bar baz': false,
'bar1 baz1': true 'bar1 baz1': true
}; };
detectChangesAndCheck(fixture, 'bar1 baz1'); detectChangesAndCheck(fixture, 'bar1 baz1');
async.done(); async.done();
}); });
})); }));
it('should split by one or more spaces between classes', it('should split by one or more spaces between classes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="objExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="objExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.objExpr = {'foo bar baz': true}; fixture.debugElement.componentInstance.objExpr = {'foo bar baz': true};
detectChangesAndCheck(fixture, 'foo bar baz'); detectChangesAndCheck(fixture, 'foo bar baz');
async.done(); async.done();
}); });
})); }));
}); });
describe('expressions evaluating to lists', () => { describe('expressions evaluating to lists', () => {
it('should add classes specified in a list literal', it('should add classes specified in a list literal',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div [ngClass]="['foo', 'bar', 'foo-bar', 'fooBar']"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div [ngClass]="['foo', 'bar', 'foo-bar', 'fooBar']"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo bar foo-bar fooBar'); detectChangesAndCheck(fixture, 'foo bar foo-bar fooBar');
async.done(); async.done();
}); });
})); }));
it('should add and remove classes based on changes to the expression', it('should add and remove classes based on changes to the expression',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="arrExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="arrExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
var arrExpr: string[] = fixture.debugElement.componentInstance.arrExpr; var arrExpr: string[] = fixture.debugElement.componentInstance.arrExpr;
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
arrExpr.push('bar'); arrExpr.push('bar');
detectChangesAndCheck(fixture, 'foo bar'); detectChangesAndCheck(fixture, 'foo bar');
arrExpr[1] = 'baz'; arrExpr[1] = 'baz';
detectChangesAndCheck(fixture, 'foo baz'); detectChangesAndCheck(fixture, 'foo baz');
ListWrapper.remove(fixture.debugElement.componentInstance.arrExpr, 'baz'); ListWrapper.remove(fixture.debugElement.componentInstance.arrExpr, 'baz');
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
async.done(); async.done();
}); });
})); }));
it('should add and remove classes when a reference changes', it('should add and remove classes when a reference changes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="arrExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="arrExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.arrExpr = ['bar']; fixture.debugElement.componentInstance.arrExpr = ['bar'];
detectChangesAndCheck(fixture, 'bar'); detectChangesAndCheck(fixture, 'bar');
async.done(); async.done();
}); });
})); }));
it('should take initial classes into account when a reference changes', it('should take initial classes into account when a reference changes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div class="foo" [ngClass]="arrExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div class="foo" [ngClass]="arrExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.arrExpr = ['bar']; fixture.debugElement.componentInstance.arrExpr = ['bar'];
detectChangesAndCheck(fixture, 'foo bar'); detectChangesAndCheck(fixture, 'foo bar');
async.done(); async.done();
}); });
})); }));
it('should ignore empty or blank class names', it('should ignore empty or blank class names',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div class="foo" [ngClass]="arrExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div class="foo" [ngClass]="arrExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.arrExpr = ['', ' ']; fixture.debugElement.componentInstance.arrExpr = ['', ' '];
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
async.done(); async.done();
}); });
})); }));
it('should trim blanks from class names', it('should trim blanks from class names',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div class="foo" [ngClass]="arrExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div class="foo" [ngClass]="arrExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.arrExpr = [' bar ']; fixture.debugElement.componentInstance.arrExpr = [' bar '];
detectChangesAndCheck(fixture, 'foo bar'); detectChangesAndCheck(fixture, 'foo bar');
async.done(); async.done();
}); });
})); }));
it('should allow multiple classes per item in arrays', it('should allow multiple classes per item in arrays',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="arrExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="arrExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.arrExpr = fixture.debugElement.componentInstance.arrExpr =
['foo bar baz', 'foo1 bar1 baz1']; ['foo bar baz', 'foo1 bar1 baz1'];
detectChangesAndCheck(fixture, 'foo bar baz foo1 bar1 baz1'); detectChangesAndCheck(fixture, 'foo bar baz foo1 bar1 baz1');
fixture.debugElement.componentInstance.arrExpr = ['foo bar baz foobar']; fixture.debugElement.componentInstance.arrExpr = ['foo bar baz foobar'];
detectChangesAndCheck(fixture, 'foo bar baz foobar'); detectChangesAndCheck(fixture, 'foo bar baz foobar');
async.done(); async.done();
}); });
})); }));
}); });
describe('expressions evaluating to sets', () => { describe('expressions evaluating to sets', () => {
it('should add and remove classes if the set instance changed', it('should add and remove classes if the set instance changed',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="setExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="setExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
var setExpr = new Set<string>(); var setExpr = new Set<string>();
setExpr.add('bar'); setExpr.add('bar');
fixture.debugElement.componentInstance.setExpr = setExpr; fixture.debugElement.componentInstance.setExpr = setExpr;
detectChangesAndCheck(fixture, 'bar'); detectChangesAndCheck(fixture, 'bar');
setExpr = new Set<string>(); setExpr = new Set<string>();
setExpr.add('baz'); setExpr.add('baz');
fixture.debugElement.componentInstance.setExpr = setExpr; fixture.debugElement.componentInstance.setExpr = setExpr;
detectChangesAndCheck(fixture, 'baz'); detectChangesAndCheck(fixture, 'baz');
async.done(); async.done();
}); });
})); }));
}); });
describe('expressions evaluating to string', () => { describe('expressions evaluating to string', () => {
it('should add classes specified in a string literal', it('should add classes specified in a string literal',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div [ngClass]="'foo bar foo-bar fooBar'"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div [ngClass]="'foo bar foo-bar fooBar'"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo bar foo-bar fooBar'); detectChangesAndCheck(fixture, 'foo bar foo-bar fooBar');
async.done(); async.done();
}); });
})); }));
it('should add and remove classes based on changes to the expression', it('should add and remove classes based on changes to the expression',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="strExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="strExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.strExpr = 'foo bar'; fixture.debugElement.componentInstance.strExpr = 'foo bar';
detectChangesAndCheck(fixture, 'foo bar'); detectChangesAndCheck(fixture, 'foo bar');
fixture.debugElement.componentInstance.strExpr = 'baz'; fixture.debugElement.componentInstance.strExpr = 'baz';
detectChangesAndCheck(fixture, 'baz'); detectChangesAndCheck(fixture, 'baz');
async.done(); async.done();
}); });
})); }));
it('should remove active classes when switching from string to null', it('should remove active classes when switching from string to null',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div [ngClass]="strExpr"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div [ngClass]="strExpr"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.strExpr = null; fixture.debugElement.componentInstance.strExpr = null;
detectChangesAndCheck(fixture, ''); detectChangesAndCheck(fixture, '');
async.done(); async.done();
}); });
})); }));
it('should take initial classes into account when switching from string to null', it('should take initial classes into account when switching from string to null',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div class="foo" [ngClass]="strExpr"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div class="foo" [ngClass]="strExpr"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
fixture.debugElement.componentInstance.strExpr = null; fixture.debugElement.componentInstance.strExpr = null;
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
async.done(); async.done();
}); });
})); }));
it('should ignore empty and blank strings', it('should ignore empty and blank strings',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div class="foo" [ngClass]="strExpr"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div class="foo" [ngClass]="strExpr"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.strExpr = ''; fixture.debugElement.componentInstance.strExpr = '';
detectChangesAndCheck(fixture, 'foo'); detectChangesAndCheck(fixture, 'foo');
async.done(); async.done();
}); });
})); }));
}); });
describe('cooperation with other class-changing constructs', () => { describe('cooperation with other class-changing constructs', () => {
it('should co-operate with the class attribute', it('should co-operate with the class attribute',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div [ngClass]="objExpr" class="init foo"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div [ngClass]="objExpr" class="init foo"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true); StringMapWrapper.set(
detectChangesAndCheck(fixture, 'init foo bar'); fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, 'init foo bar');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'foo', false); StringMapWrapper.set(
detectChangesAndCheck(fixture, 'init bar'); fixture.debugElement.componentInstance.objExpr, 'foo', false);
detectChangesAndCheck(fixture, 'init bar');
fixture.debugElement.componentInstance.objExpr = null; fixture.debugElement.componentInstance.objExpr = null;
detectChangesAndCheck(fixture, 'init foo'); detectChangesAndCheck(fixture, 'init foo');
async.done(); async.done();
}); });
})); }));
it('should co-operate with the interpolated class attribute', it('should co-operate with the interpolated class attribute',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div [ngClass]="objExpr" class="{{'init foo'}}"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div [ngClass]="objExpr" class="{{'init foo'}}"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true); StringMapWrapper.set(
detectChangesAndCheck(fixture, `init foo bar`); fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, `init foo bar`);
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'foo', false); StringMapWrapper.set(
detectChangesAndCheck(fixture, `init bar`); fixture.debugElement.componentInstance.objExpr, 'foo', false);
detectChangesAndCheck(fixture, `init bar`);
fixture.debugElement.componentInstance.objExpr = null; fixture.debugElement.componentInstance.objExpr = null;
detectChangesAndCheck(fixture, `init foo`); detectChangesAndCheck(fixture, `init foo`);
async.done(); async.done();
}); });
})); }));
it('should co-operate with the class attribute and binding to it', it('should co-operate with the class attribute and binding to it',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div [ngClass]="objExpr" class="init" [class]="'foo'"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div [ngClass]="objExpr" class="init" [class]="'foo'"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true); StringMapWrapper.set(
detectChangesAndCheck(fixture, `init foo bar`); fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, `init foo bar`);
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'foo', false); StringMapWrapper.set(
detectChangesAndCheck(fixture, `init bar`); fixture.debugElement.componentInstance.objExpr, 'foo', false);
detectChangesAndCheck(fixture, `init bar`);
fixture.debugElement.componentInstance.objExpr = null; fixture.debugElement.componentInstance.objExpr = null;
detectChangesAndCheck(fixture, `init foo`); detectChangesAndCheck(fixture, `init foo`);
async.done(); async.done();
}); });
})); }));
it('should co-operate with the class attribute and class.name binding', it('should co-operate with the class attribute and class.name binding',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
'<div class="init foo" [ngClass]="objExpr" [class.baz]="condition"></div>'; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template =
'<div class="init foo" [ngClass]="objExpr" [class.baz]="condition"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'init foo baz'); detectChangesAndCheck(fixture, 'init foo baz');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true); StringMapWrapper.set(
detectChangesAndCheck(fixture, 'init foo baz bar'); fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, 'init foo baz bar');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'foo', false); StringMapWrapper.set(
detectChangesAndCheck(fixture, 'init baz bar'); fixture.debugElement.componentInstance.objExpr, 'foo', false);
detectChangesAndCheck(fixture, 'init baz bar');
fixture.debugElement.componentInstance.condition = false; fixture.debugElement.componentInstance.condition = false;
detectChangesAndCheck(fixture, 'init bar'); detectChangesAndCheck(fixture, 'init bar');
async.done(); async.done();
}); });
})); }));
it('should co-operate with initial class and class attribute binding when binding changes', it('should co-operate with initial class and class attribute binding when binding changes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div class="init" [ngClass]="objExpr" [class]="strExpr"></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = '<div class="init" [ngClass]="objExpr" [class]="strExpr"></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
detectChangesAndCheck(fixture, 'init foo'); detectChangesAndCheck(fixture, 'init foo');
StringMapWrapper.set(fixture.debugElement.componentInstance.objExpr, 'bar', true); StringMapWrapper.set(
detectChangesAndCheck(fixture, 'init foo bar'); fixture.debugElement.componentInstance.objExpr, 'bar', true);
detectChangesAndCheck(fixture, 'init foo bar');
fixture.debugElement.componentInstance.strExpr = 'baz'; fixture.debugElement.componentInstance.strExpr = 'baz';
detectChangesAndCheck(fixture, 'init bar baz foo'); detectChangesAndCheck(fixture, 'init bar baz foo');
fixture.debugElement.componentInstance.objExpr = null; fixture.debugElement.componentInstance.objExpr = null;
detectChangesAndCheck(fixture, 'init baz'); detectChangesAndCheck(fixture, 'init baz');
async.done(); async.done();
}); });
})); }));
}); });
}) })

View File

@ -1,13 +1,4 @@
import { import {beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
beforeEach,
beforeEachProviders,
ddescribe,
describe,
iit,
inject,
it,
xit,
} from '@angular/core/testing/testing_internal';
import {expect} from '@angular/platform-browser/testing'; import {expect} from '@angular/platform-browser/testing';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing'; import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing';
@ -25,482 +16,535 @@ export function main() {
'<div><copy-me template="ngFor let item of items">{{item.toString()}};</copy-me></div>'; '<div><copy-me template="ngFor let item of items">{{item.toString()}};</copy-me></div>';
it('should reflect initial elements', it('should reflect initial elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate(TestComponent, TEMPLATE) [TestComponentBuilder, AsyncTestCompleter],
.createAsync(TestComponent) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.then((fixture) => { tcb.overrideTemplate(TestComponent, TEMPLATE)
fixture.detectChanges(); .createAsync(TestComponent)
expect(fixture.debugElement.nativeElement).toHaveText('1;2;'); .then((fixture) => {
async.done(); fixture.detectChanges();
}); expect(fixture.debugElement.nativeElement).toHaveText('1;2;');
})); async.done();
});
}));
it('should reflect added elements', it('should reflect added elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate(TestComponent, TEMPLATE) [TestComponentBuilder, AsyncTestCompleter],
.createAsync(TestComponent) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.then((fixture) => { tcb.overrideTemplate(TestComponent, TEMPLATE)
fixture.detectChanges(); .createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
(<number[]>fixture.debugElement.componentInstance.items).push(3); (<number[]>fixture.debugElement.componentInstance.items).push(3);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('1;2;3;'); expect(fixture.debugElement.nativeElement).toHaveText('1;2;3;');
async.done(); async.done();
}); });
})); }));
it('should reflect removed elements', it('should reflect removed elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate(TestComponent, TEMPLATE) [TestComponentBuilder, AsyncTestCompleter],
.createAsync(TestComponent) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.then((fixture) => { tcb.overrideTemplate(TestComponent, TEMPLATE)
fixture.detectChanges(); .createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 1); ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 1);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('1;'); expect(fixture.debugElement.nativeElement).toHaveText('1;');
async.done(); async.done();
}); });
})); }));
it('should reflect moved elements', it('should reflect moved elements',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate(TestComponent, TEMPLATE) [TestComponentBuilder, AsyncTestCompleter],
.createAsync(TestComponent) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.then((fixture) => { tcb.overrideTemplate(TestComponent, TEMPLATE)
fixture.detectChanges(); .createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 0); ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 0);
(<number[]>fixture.debugElement.componentInstance.items).push(1); (<number[]>fixture.debugElement.componentInstance.items).push(1);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('2;1;'); expect(fixture.debugElement.nativeElement).toHaveText('2;1;');
async.done(); async.done();
}); });
})); }));
it('should reflect a mix of all changes (additions/removals/moves)', it('should reflect a mix of all changes (additions/removals/moves)',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate(TestComponent, TEMPLATE) [TestComponentBuilder, AsyncTestCompleter],
.createAsync(TestComponent) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.then((fixture) => { tcb.overrideTemplate(TestComponent, TEMPLATE)
fixture.debugElement.componentInstance.items = [0, 1, 2, 3, 4, 5]; .createAsync(TestComponent)
fixture.detectChanges(); .then((fixture) => {
fixture.debugElement.componentInstance.items = [0, 1, 2, 3, 4, 5];
fixture.detectChanges();
fixture.debugElement.componentInstance.items = [6, 2, 7, 0, 4, 8]; fixture.debugElement.componentInstance.items = [6, 2, 7, 0, 4, 8];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('6;2;7;0;4;8;'); expect(fixture.debugElement.nativeElement).toHaveText('6;2;7;0;4;8;');
async.done(); async.done();
}); });
})); }));
it('should iterate over an array of objects', it('should iterate over an array of objects',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<ul><li template="ngFor let item of items">{{item["name"]}};</li></ul>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template =
'<ul><li template="ngFor let item of items">{{item["name"]}};</li></ul>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
// INIT // INIT
fixture.debugElement.componentInstance.items = fixture.debugElement.componentInstance.items =
[{'name': 'misko'}, {'name': 'shyam'}]; [{'name': 'misko'}, {'name': 'shyam'}];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('misko;shyam;'); expect(fixture.debugElement.nativeElement).toHaveText('misko;shyam;');
// GROW // GROW
(<any[]>fixture.debugElement.componentInstance.items).push({'name': 'adam'}); (<any[]>fixture.debugElement.componentInstance.items).push({'name': 'adam'});
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('misko;shyam;adam;'); expect(fixture.debugElement.nativeElement).toHaveText('misko;shyam;adam;');
// SHRINK // SHRINK
ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 2); ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 2);
ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 0); ListWrapper.removeAt(fixture.debugElement.componentInstance.items, 0);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('shyam;'); expect(fixture.debugElement.nativeElement).toHaveText('shyam;');
async.done(); async.done();
}); });
})); }));
it('should gracefully handle nulls', it('should gracefully handle nulls',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<ul><li template="ngFor let item of null">{{item}};</li></ul>'; [TestComponentBuilder, AsyncTestCompleter],
tcb.overrideTemplate(TestComponent, template) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.createAsync(TestComponent) var template = '<ul><li template="ngFor let item of null">{{item}};</li></ul>';
.then((fixture) => { tcb.overrideTemplate(TestComponent, template)
fixture.detectChanges(); .createAsync(TestComponent)
expect(fixture.debugElement.nativeElement).toHaveText(''); .then((fixture) => {
async.done(); fixture.detectChanges();
}); expect(fixture.debugElement.nativeElement).toHaveText('');
})); async.done();
});
}));
it('should gracefully handle ref changing to null and back', it('should gracefully handle ref changing to null and back',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate(TestComponent, TEMPLATE) [TestComponentBuilder, AsyncTestCompleter],
.createAsync(TestComponent) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.then((fixture) => { tcb.overrideTemplate(TestComponent, TEMPLATE)
fixture.detectChanges(); .createAsync(TestComponent)
expect(fixture.debugElement.nativeElement).toHaveText('1;2;'); .then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('1;2;');
fixture.debugElement.componentInstance.items = null; fixture.debugElement.componentInstance.items = null;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText(''); expect(fixture.debugElement.nativeElement).toHaveText('');
fixture.debugElement.componentInstance.items = [1, 2, 3]; fixture.debugElement.componentInstance.items = [1, 2, 3];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('1;2;3;'); expect(fixture.debugElement.nativeElement).toHaveText('1;2;3;');
async.done(); async.done();
}); });
})); }));
if (!IS_DART) { if (!IS_DART) {
it('should throw on non-iterable ref and suggest using an array', it('should throw on non-iterable ref and suggest using an array',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate(TestComponent, TEMPLATE) [TestComponentBuilder, AsyncTestCompleter],
.createAsync(TestComponent) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.then((fixture) => { tcb.overrideTemplate(TestComponent, TEMPLATE)
fixture.debugElement.componentInstance.items = 'whaaa'; .createAsync(TestComponent)
try { .then((fixture) => {
fixture.detectChanges() fixture.debugElement.componentInstance.items = 'whaaa';
} catch (e) { try {
expect(e.message).toContain( fixture.detectChanges()
`Cannot find a differ supporting object 'whaaa' of type 'string'. NgFor only supports binding to Iterables such as Arrays.`); } catch (e) {
async.done(); expect(e.message).toContain(
} `Cannot find a differ supporting object 'whaaa' of type 'string'. NgFor only supports binding to Iterables such as Arrays.`);
}); async.done();
})); }
});
}));
} }
it('should throw on ref changing to string', it('should throw on ref changing to string',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate(TestComponent, TEMPLATE) [TestComponentBuilder, AsyncTestCompleter],
.createAsync(TestComponent) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.then((fixture) => { tcb.overrideTemplate(TestComponent, TEMPLATE)
fixture.detectChanges(); .createAsync(TestComponent)
expect(fixture.debugElement.nativeElement).toHaveText('1;2;'); .then((fixture) => {
fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('1;2;');
fixture.debugElement.componentInstance.items = 'whaaa'; fixture.debugElement.componentInstance.items = 'whaaa';
expect(() => fixture.detectChanges()).toThrowError(); expect(() => fixture.detectChanges()).toThrowError();
async.done(); async.done();
}); });
})); }));
it('should works with duplicates', it('should works with duplicates',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate(TestComponent, TEMPLATE) [TestComponentBuilder, AsyncTestCompleter],
.createAsync(TestComponent) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.then((fixture) => { tcb.overrideTemplate(TestComponent, TEMPLATE)
var a = new Foo(); .createAsync(TestComponent)
fixture.debugElement.componentInstance.items = [a, a]; .then((fixture) => {
fixture.detectChanges(); var a = new Foo();
expect(fixture.debugElement.nativeElement).toHaveText('foo;foo;'); fixture.debugElement.componentInstance.items = [a, a];
async.done(); fixture.detectChanges();
}); expect(fixture.debugElement.nativeElement).toHaveText('foo;foo;');
})); async.done();
});
}));
it('should repeat over nested arrays', it('should repeat over nested arrays',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div>' + [TestComponentBuilder, AsyncTestCompleter],
'<div template="ngFor let item of items">' + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'<div template="ngFor let subitem of item">' + var template = '<div>' +
'{{subitem}}-{{item.length}};' + '<div template="ngFor let item of items">' +
'</div>|' + '<div template="ngFor let subitem of item">' +
'</div>' + '{{subitem}}-{{item.length}};' +
'</div>'; '</div>|' +
'</div>' +
'</div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.items = [['a', 'b'], ['c']]; fixture.debugElement.componentInstance.items = [['a', 'b'], ['c']];
fixture.detectChanges(); fixture.detectChanges();
fixture.detectChanges(); fixture.detectChanges();
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('a-2;b-2;|c-1;|'); expect(fixture.debugElement.nativeElement).toHaveText('a-2;b-2;|c-1;|');
fixture.debugElement.componentInstance.items = [['e'], ['f', 'g']]; fixture.debugElement.componentInstance.items = [['e'], ['f', 'g']];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('e-1;|f-2;g-2;|'); expect(fixture.debugElement.nativeElement).toHaveText('e-1;|f-2;g-2;|');
async.done(); async.done();
}); });
})); }));
it('should repeat over nested arrays with no intermediate element', it('should repeat over nested arrays with no intermediate element',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div><template ngFor let-item [ngForOf]="items">' + [TestComponentBuilder, AsyncTestCompleter],
'<div template="ngFor let subitem of item">' + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'{{subitem}}-{{item.length}};' + var template = '<div><template ngFor let-item [ngForOf]="items">' +
'</div></template></div>'; '<div template="ngFor let subitem of item">' +
'{{subitem}}-{{item.length}};' +
'</div></template></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.items = [['a', 'b'], ['c']]; fixture.debugElement.componentInstance.items = [['a', 'b'], ['c']];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('a-2;b-2;c-1;'); expect(fixture.debugElement.nativeElement).toHaveText('a-2;b-2;c-1;');
fixture.debugElement.componentInstance.items = [['e'], ['f', 'g']]; fixture.debugElement.componentInstance.items = [['e'], ['f', 'g']];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('e-1;f-2;g-2;'); expect(fixture.debugElement.nativeElement).toHaveText('e-1;f-2;g-2;');
async.done(); async.done();
}); });
})); }));
it('should repeat over nested ngIf that are the last node in the ngFor temlate', it('should repeat over nested ngIf that are the last node in the ngFor temlate',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
`<div><template ngFor let-item [ngForOf]="items" let-i="index"><div>{{i}}|</div>` + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
`<div *ngIf="i % 2 == 0">even|</div></template></div>`; var template =
`<div><template ngFor let-item [ngForOf]="items" let-i="index"><div>{{i}}|</div>` +
`<div *ngIf="i % 2 == 0">even|</div></template></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
var el = fixture.debugElement.nativeElement; var el = fixture.debugElement.nativeElement;
var items = [1]; var items = [1];
fixture.debugElement.componentInstance.items = items; fixture.debugElement.componentInstance.items = items;
fixture.detectChanges(); fixture.detectChanges();
expect(el).toHaveText('0|even|'); expect(el).toHaveText('0|even|');
items.push(1); items.push(1);
fixture.detectChanges(); fixture.detectChanges();
expect(el).toHaveText('0|even|1|'); expect(el).toHaveText('0|even|1|');
items.push(1); items.push(1);
fixture.detectChanges(); fixture.detectChanges();
expect(el).toHaveText('0|even|1|2|even|'); expect(el).toHaveText('0|even|1|2|even|');
async.done(); async.done();
}); });
})); }));
it('should display indices correctly', it('should display indices correctly',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
'<div><copy-me template="ngFor: let item of items; let i=index">{{i.toString()}}</copy-me></div>'; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template =
'<div><copy-me template="ngFor: let item of items; let i=index">{{i.toString()}}</copy-me></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; fixture.debugElement.componentInstance.items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('0123456789'); expect(fixture.debugElement.nativeElement).toHaveText('0123456789');
fixture.debugElement.componentInstance.items = [1, 2, 6, 7, 4, 3, 5, 8, 9, 0]; fixture.debugElement.componentInstance.items = [1, 2, 6, 7, 4, 3, 5, 8, 9, 0];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('0123456789'); expect(fixture.debugElement.nativeElement).toHaveText('0123456789');
async.done(); async.done();
}); });
})); }));
it('should display first item correctly', it('should display first item correctly',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
'<div><copy-me template="ngFor: let item of items; let isFirst=first">{{isFirst.toString()}}</copy-me></div>'; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template =
'<div><copy-me template="ngFor: let item of items; let isFirst=first">{{isFirst.toString()}}</copy-me></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.items = [0, 1, 2]; fixture.debugElement.componentInstance.items = [0, 1, 2];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('truefalsefalse'); expect(fixture.debugElement.nativeElement).toHaveText('truefalsefalse');
fixture.debugElement.componentInstance.items = [2, 1]; fixture.debugElement.componentInstance.items = [2, 1];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('truefalse'); expect(fixture.debugElement.nativeElement).toHaveText('truefalse');
async.done(); async.done();
}); });
})); }));
it('should display last item correctly', it('should display last item correctly',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
'<div><copy-me template="ngFor: let item of items; let isLast=last">{{isLast.toString()}}</copy-me></div>'; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template =
'<div><copy-me template="ngFor: let item of items; let isLast=last">{{isLast.toString()}}</copy-me></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.items = [0, 1, 2]; fixture.debugElement.componentInstance.items = [0, 1, 2];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('falsefalsetrue'); expect(fixture.debugElement.nativeElement).toHaveText('falsefalsetrue');
fixture.debugElement.componentInstance.items = [2, 1]; fixture.debugElement.componentInstance.items = [2, 1];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('falsetrue'); expect(fixture.debugElement.nativeElement).toHaveText('falsetrue');
async.done(); async.done();
}); });
})); }));
it('should display even items correctly', it('should display even items correctly',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
'<div><copy-me template="ngFor: let item of items; let isEven=even">{{isEven.toString()}}</copy-me></div>'; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template =
'<div><copy-me template="ngFor: let item of items; let isEven=even">{{isEven.toString()}}</copy-me></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.items = [0, 1, 2]; fixture.debugElement.componentInstance.items = [0, 1, 2];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('truefalsetrue'); expect(fixture.debugElement.nativeElement).toHaveText('truefalsetrue');
fixture.debugElement.componentInstance.items = [2, 1]; fixture.debugElement.componentInstance.items = [2, 1];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('truefalse'); expect(fixture.debugElement.nativeElement).toHaveText('truefalse');
async.done(); async.done();
}); });
})); }));
it('should display odd items correctly', it('should display odd items correctly',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
'<div><copy-me template="ngFor: let item of items; let isOdd=odd">{{isOdd.toString()}}</copy-me></div>'; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template =
'<div><copy-me template="ngFor: let item of items; let isOdd=odd">{{isOdd.toString()}}</copy-me></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.items = [0, 1, 2, 3]; fixture.debugElement.componentInstance.items = [0, 1, 2, 3];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('falsetruefalsetrue'); expect(fixture.debugElement.nativeElement).toHaveText('falsetruefalsetrue');
fixture.debugElement.componentInstance.items = [2, 1]; fixture.debugElement.componentInstance.items = [2, 1];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('falsetrue'); expect(fixture.debugElement.nativeElement).toHaveText('falsetrue');
async.done(); async.done();
}); });
})); }));
it('should allow to use a custom template', it('should allow to use a custom template',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate( [TestComponentBuilder, AsyncTestCompleter],
TestComponent, (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'<ul><template ngFor [ngForOf]="items" [ngForTemplate]="contentTpl"></template></ul>') tcb.overrideTemplate(
.overrideTemplate( TestComponent,
ComponentUsingTestComponent, '<ul><template ngFor [ngForOf]="items" [ngForTemplate]="contentTpl"></template></ul>')
'<test-cmp><li template="let item; let i=index">{{i}}: {{item}};</li></test-cmp>') .overrideTemplate(
.createAsync(ComponentUsingTestComponent) ComponentUsingTestComponent,
.then((fixture) => { '<test-cmp><li template="let item; let i=index">{{i}}: {{item}};</li></test-cmp>')
var testComponent = fixture.debugElement.children[0]; .createAsync(ComponentUsingTestComponent)
testComponent.componentInstance.items = ['a', 'b', 'c']; .then((fixture) => {
fixture.detectChanges(); var testComponent = fixture.debugElement.children[0];
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;'); testComponent.componentInstance.items = ['a', 'b', 'c'];
fixture.detectChanges();
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
async.done(); async.done();
}); });
})); }));
it('should use a default template if a custom one is null', it('should use a default template if a custom one is null',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate(TestComponent, `<ul><template ngFor let-item [ngForOf]="items" [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideTemplate(TestComponent, `<ul><template ngFor let-item [ngForOf]="items"
[ngForTemplate]="contentTpl" let-i="index">{{i}}: {{item}};</template></ul>`) [ngForTemplate]="contentTpl" let-i="index">{{i}}: {{item}};</template></ul>`)
.overrideTemplate(ComponentUsingTestComponent, '<test-cmp></test-cmp>') .overrideTemplate(ComponentUsingTestComponent, '<test-cmp></test-cmp>')
.createAsync(ComponentUsingTestComponent) .createAsync(ComponentUsingTestComponent)
.then((fixture) => { .then((fixture) => {
var testComponent = fixture.debugElement.children[0]; var testComponent = fixture.debugElement.children[0];
testComponent.componentInstance.items = ['a', 'b', 'c']; testComponent.componentInstance.items = ['a', 'b', 'c'];
fixture.detectChanges(); fixture.detectChanges();
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;'); expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
async.done(); async.done();
}); });
})); }));
it('should use a custom template when both default and a custom one are present', it('should use a custom template when both default and a custom one are present',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
tcb.overrideTemplate(TestComponent, `<ul><template ngFor let-item [ngForOf]="items" [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideTemplate(TestComponent, `<ul><template ngFor let-item [ngForOf]="items"
[ngForTemplate]="contentTpl" let-i="index">{{i}}=> {{item}};</template></ul>`) [ngForTemplate]="contentTpl" let-i="index">{{i}}=> {{item}};</template></ul>`)
.overrideTemplate( .overrideTemplate(
ComponentUsingTestComponent, ComponentUsingTestComponent,
'<test-cmp><li template="let item; let i=index">{{i}}: {{item}};</li></test-cmp>') '<test-cmp><li template="let item; let i=index">{{i}}: {{item}};</li></test-cmp>')
.createAsync(ComponentUsingTestComponent) .createAsync(ComponentUsingTestComponent)
.then((fixture) => { .then((fixture) => {
var testComponent = fixture.debugElement.children[0]; var testComponent = fixture.debugElement.children[0];
testComponent.componentInstance.items = ['a', 'b', 'c']; testComponent.componentInstance.items = ['a', 'b', 'c'];
fixture.detectChanges(); fixture.detectChanges();
expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;'); expect(testComponent.nativeElement).toHaveText('0: a;1: b;2: c;');
async.done(); async.done();
}); });
})); }));
describe('track by', function() { describe('track by', function() {
it('should not replace tracked items', it('should not replace tracked items',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById" let-i="index"> (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template =
`<template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById" let-i="index">
<p>{{items[i]}}</p> <p>{{items[i]}}</p>
</template>`; </template>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
var buildItemList = var buildItemList =
() => { () => {
fixture.debugElement.componentInstance.items = [{'id': 'a'}]; fixture.debugElement.componentInstance.items = [{'id': 'a'}];
fixture.detectChanges(); fixture.detectChanges();
return fixture.debugElement.queryAll(By.css('p'))[0]; return fixture.debugElement.queryAll(By.css('p'))[0];
} }
var firstP = buildItemList(); var firstP = buildItemList();
var finalP = buildItemList(); var finalP = buildItemList();
expect(finalP.nativeElement).toBe(firstP.nativeElement); expect(finalP.nativeElement).toBe(firstP.nativeElement);
async.done(); async.done();
}); });
})); }));
it('should update implicit local variable on view', it('should update implicit local variable on view',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
`<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById">{{item['color']}}</template></div>`; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideTemplate(TestComponent, template) var template =
.createAsync(TestComponent) `<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById">{{item['color']}}</template></div>`;
.then((fixture) => { tcb.overrideTemplate(TestComponent, template)
fixture.debugElement.componentInstance.items = [{'id': 'a', 'color': 'blue'}]; .createAsync(TestComponent)
fixture.detectChanges(); .then((fixture) => {
expect(fixture.debugElement.nativeElement).toHaveText('blue'); fixture.debugElement.componentInstance.items = [{'id': 'a', 'color': 'blue'}];
fixture.debugElement.componentInstance.items = [{'id': 'a', 'color': 'red'}]; fixture.detectChanges();
fixture.detectChanges(); expect(fixture.debugElement.nativeElement).toHaveText('blue');
expect(fixture.debugElement.nativeElement).toHaveText('red'); fixture.debugElement.componentInstance.items = [{'id': 'a', 'color': 'red'}];
async.done(); fixture.detectChanges();
}); expect(fixture.debugElement.nativeElement).toHaveText('red');
})); async.done();
});
}));
it('should move items around and keep them updated ', it('should move items around and keep them updated ',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
`<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById">{{item['color']}}</template></div>`; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideTemplate(TestComponent, template) var template =
.createAsync(TestComponent) `<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackById">{{item['color']}}</template></div>`;
.then((fixture) => { tcb.overrideTemplate(TestComponent, template)
fixture.debugElement.componentInstance.items = .createAsync(TestComponent)
[{'id': 'a', 'color': 'blue'}, {'id': 'b', 'color': 'yellow'}]; .then((fixture) => {
fixture.detectChanges(); fixture.debugElement.componentInstance.items =
expect(fixture.debugElement.nativeElement).toHaveText('blueyellow'); [{'id': 'a', 'color': 'blue'}, {'id': 'b', 'color': 'yellow'}];
fixture.debugElement.componentInstance.items = fixture.detectChanges();
[{'id': 'b', 'color': 'orange'}, {'id': 'a', 'color': 'red'}]; expect(fixture.debugElement.nativeElement).toHaveText('blueyellow');
fixture.detectChanges(); fixture.debugElement.componentInstance.items =
expect(fixture.debugElement.nativeElement).toHaveText('orangered'); [{'id': 'b', 'color': 'orange'}, {'id': 'a', 'color': 'red'}];
async.done(); fixture.detectChanges();
}); expect(fixture.debugElement.nativeElement).toHaveText('orangered');
})); async.done();
});
}));
it('should handle added and removed items properly when tracking by index', it('should handle added and removed items properly when tracking by index',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
`<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackByIndex">{{item}}</template></div>`; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideTemplate(TestComponent, template) var template =
.createAsync(TestComponent) `<div><template ngFor let-item [ngForOf]="items" [ngForTrackBy]="trackByIndex">{{item}}</template></div>`;
.then((fixture) => { tcb.overrideTemplate(TestComponent, template)
fixture.debugElement.componentInstance.items = ['a', 'b', 'c', 'd']; .createAsync(TestComponent)
fixture.detectChanges(); .then((fixture) => {
fixture.debugElement.componentInstance.items = ['e', 'f', 'g', 'h']; fixture.debugElement.componentInstance.items = ['a', 'b', 'c', 'd'];
fixture.detectChanges(); fixture.detectChanges();
fixture.debugElement.componentInstance.items = ['e', 'f', 'h']; fixture.debugElement.componentInstance.items = ['e', 'f', 'g', 'h'];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('efh'); fixture.debugElement.componentInstance.items = ['e', 'f', 'h'];
async.done(); fixture.detectChanges();
}); expect(fixture.debugElement.nativeElement).toHaveText('efh');
})); async.done();
});
}));
}); });
}); });
} }

View File

@ -1,12 +1,4 @@
import { import {beforeEach, ddescribe, describe, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
beforeEach,
ddescribe,
describe,
iit,
inject,
it,
xit,
} from '@angular/core/testing/testing_internal';
import {expect} from '@angular/platform-browser/testing'; import {expect} from '@angular/platform-browser/testing';
import {TestComponentBuilder} from '@angular/compiler/testing'; import {TestComponentBuilder} from '@angular/compiler/testing';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
@ -21,222 +13,252 @@ import {IS_DART} from '../../src/facade/lang';
export function main() { export function main() {
describe('ngIf directive', () => { describe('ngIf directive', () => {
it('should work in a template attribute', it('should work in a template attribute',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var html = '<div><copy-me template="ngIf booleanCondition">hello</copy-me></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var html = '<div><copy-me template="ngIf booleanCondition">hello</copy-me></div>';
tcb.overrideTemplate(TestComponent, html) tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(1); .length)
expect(fixture.debugElement.nativeElement).toHaveText('hello'); .toEqual(1);
async.done(); expect(fixture.debugElement.nativeElement).toHaveText('hello');
}); async.done();
})); });
}));
it('should work in a template element', it('should work in a template element',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var html = [TestComponentBuilder, AsyncTestCompleter],
'<div><template [ngIf]="booleanCondition"><copy-me>hello2</copy-me></template></div>'; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var html =
'<div><template [ngIf]="booleanCondition"><copy-me>hello2</copy-me></template></div>';
tcb.overrideTemplate(TestComponent, html) tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(1); .length)
expect(fixture.debugElement.nativeElement).toHaveText('hello2'); .toEqual(1);
async.done(); expect(fixture.debugElement.nativeElement).toHaveText('hello2');
}); async.done();
})); });
}));
it('should toggle node when condition changes', it('should toggle node when condition changes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var html = '<div><copy-me template="ngIf booleanCondition">hello</copy-me></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var html = '<div><copy-me template="ngIf booleanCondition">hello</copy-me></div>';
tcb.overrideTemplate(TestComponent, html) tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.booleanCondition = false; fixture.debugElement.componentInstance.booleanCondition = false;
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(0); .length)
expect(fixture.debugElement.nativeElement).toHaveText(''); .toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText('');
fixture.debugElement.componentInstance.booleanCondition = true; fixture.debugElement.componentInstance.booleanCondition = true;
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(1); .length)
expect(fixture.debugElement.nativeElement).toHaveText('hello'); .toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello');
fixture.debugElement.componentInstance.booleanCondition = false; fixture.debugElement.componentInstance.booleanCondition = false;
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(0); .length)
expect(fixture.debugElement.nativeElement).toHaveText(''); .toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText('');
async.done(); async.done();
}); });
})); }));
it('should handle nested if correctly', it('should handle nested if correctly',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var html = [TestComponentBuilder, AsyncTestCompleter],
'<div><template [ngIf]="booleanCondition"><copy-me *ngIf="nestedBooleanCondition">hello</copy-me></template></div>'; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var html =
'<div><template [ngIf]="booleanCondition"><copy-me *ngIf="nestedBooleanCondition">hello</copy-me></template></div>';
tcb.overrideTemplate(TestComponent, html) tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.booleanCondition = false; fixture.debugElement.componentInstance.booleanCondition = false;
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(0); .length)
expect(fixture.debugElement.nativeElement).toHaveText(''); .toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText('');
fixture.debugElement.componentInstance.booleanCondition = true; fixture.debugElement.componentInstance.booleanCondition = true;
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(1); .length)
expect(fixture.debugElement.nativeElement).toHaveText('hello'); .toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello');
fixture.debugElement.componentInstance.nestedBooleanCondition = false; fixture.debugElement.componentInstance.nestedBooleanCondition = false;
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(0); .length)
expect(fixture.debugElement.nativeElement).toHaveText(''); .toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText('');
fixture.debugElement.componentInstance.nestedBooleanCondition = true; fixture.debugElement.componentInstance.nestedBooleanCondition = true;
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(1); .length)
expect(fixture.debugElement.nativeElement).toHaveText('hello'); .toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello');
fixture.debugElement.componentInstance.booleanCondition = false; fixture.debugElement.componentInstance.booleanCondition = false;
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(0); .length)
expect(fixture.debugElement.nativeElement).toHaveText(''); .toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText('');
async.done(); async.done();
}); });
})); }));
it('should update several nodes with if', it('should update several nodes with if',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var html = [TestComponentBuilder, AsyncTestCompleter],
'<div>' + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'<copy-me template="ngIf numberCondition + 1 >= 2">helloNumber</copy-me>' + var html = '<div>' +
'<copy-me template="ngIf stringCondition == \'foo\'">helloString</copy-me>' + '<copy-me template="ngIf numberCondition + 1 >= 2">helloNumber</copy-me>' +
'<copy-me template="ngIf functionCondition(stringCondition, numberCondition)">helloFunction</copy-me>' + '<copy-me template="ngIf stringCondition == \'foo\'">helloString</copy-me>' +
'</div>'; '<copy-me template="ngIf functionCondition(stringCondition, numberCondition)">helloFunction</copy-me>' +
'</div>';
tcb.overrideTemplate(TestComponent, html) tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(3); .length)
expect(getDOM().getText(fixture.debugElement.nativeElement)) .toEqual(3);
.toEqual('helloNumberhelloStringhelloFunction'); expect(getDOM().getText(fixture.debugElement.nativeElement))
.toEqual('helloNumberhelloStringhelloFunction');
fixture.debugElement.componentInstance.numberCondition = 0; fixture.debugElement.componentInstance.numberCondition = 0;
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(1); .length)
expect(fixture.debugElement.nativeElement).toHaveText('helloString'); .toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('helloString');
fixture.debugElement.componentInstance.numberCondition = 1; fixture.debugElement.componentInstance.numberCondition = 1;
fixture.debugElement.componentInstance.stringCondition = "bar"; fixture.debugElement.componentInstance.stringCondition = 'bar';
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM()
getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'copy-me').length) .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.toEqual(1); .length)
expect(fixture.debugElement.nativeElement).toHaveText('helloNumber'); .toEqual(1);
async.done(); expect(fixture.debugElement.nativeElement).toHaveText('helloNumber');
}); async.done();
})); });
}));
if (!IS_DART) { if (!IS_DART) {
it('should not add the element twice if the condition goes from true to true (JS)', it('should not add the element twice if the condition goes from true to true (JS)',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var html = '<div><copy-me template="ngIf numberCondition">hello</copy-me></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var html = '<div><copy-me template="ngIf numberCondition">hello</copy-me></div>';
tcb.overrideTemplate(TestComponent, html) tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
expect(getDOM() expect(getDOM()
.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me') .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.length) .length)
.toEqual(1); .toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello'); expect(fixture.debugElement.nativeElement).toHaveText('hello');
fixture.debugElement.componentInstance.numberCondition = 2; fixture.debugElement.componentInstance.numberCondition = 2;
fixture.detectChanges(); fixture.detectChanges();
expect(getDOM() expect(getDOM()
.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me') .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.length) .length)
.toEqual(1); .toEqual(1);
expect(fixture.debugElement.nativeElement).toHaveText('hello'); expect(fixture.debugElement.nativeElement).toHaveText('hello');
async.done(); async.done();
}); });
})); }));
it('should not recreate the element if the condition goes from true to true (JS)', it('should not recreate the element if the condition goes from true to true (JS)',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var html = '<div><copy-me template="ngIf numberCondition">hello</copy-me></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var html = '<div><copy-me template="ngIf numberCondition">hello</copy-me></div>';
tcb.overrideTemplate(TestComponent, html) tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
getDOM().addClass( getDOM().addClass(
getDOM().querySelector(fixture.debugElement.nativeElement, 'copy-me'), "foo"); getDOM().querySelector(fixture.debugElement.nativeElement, 'copy-me'),
'foo');
fixture.debugElement.componentInstance.numberCondition = 2; fixture.debugElement.componentInstance.numberCondition = 2;
fixture.detectChanges(); fixture.detectChanges();
expect(getDOM().hasClass( expect(
getDOM().querySelector(fixture.debugElement.nativeElement, 'copy-me'), getDOM().hasClass(
"foo")) getDOM().querySelector(fixture.debugElement.nativeElement, 'copy-me'),
.toBe(true); 'foo'))
.toBe(true);
async.done(); async.done();
}); });
})); }));
} }
if (IS_DART) { if (IS_DART) {
it('should not create the element if the condition is not a boolean (DART)', it('should not create the element if the condition is not a boolean (DART)',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var html = '<div><copy-me template="ngIf numberCondition">hello</copy-me></div>'; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var html = '<div><copy-me template="ngIf numberCondition">hello</copy-me></div>';
tcb.overrideTemplate(TestComponent, html) tcb.overrideTemplate(TestComponent, html)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
expect(() => fixture.detectChanges()).toThrowError(); expect(() => fixture.detectChanges()).toThrowError();
expect(getDOM() expect(getDOM()
.querySelectorAll(fixture.debugElement.nativeElement, 'copy-me') .querySelectorAll(fixture.debugElement.nativeElement, 'copy-me')
.length) .length)
.toEqual(0); .toEqual(0);
expect(fixture.debugElement.nativeElement).toHaveText(''); expect(fixture.debugElement.nativeElement).toHaveText('');
async.done(); async.done();
}); });
})); }));
} }
}); });
@ -253,7 +275,9 @@ class TestComponent {
this.booleanCondition = true; this.booleanCondition = true;
this.nestedBooleanCondition = true; this.nestedBooleanCondition = true;
this.numberCondition = 1; this.numberCondition = 1;
this.stringCondition = "foo"; this.stringCondition = 'foo';
this.functionCondition = function(s: any /** TODO #9100 */, n: any /** TODO #9100 */) { return s == "foo" && n == 1; }; this.functionCondition = function(s: any /** TODO #9100 */, n: any /** TODO #9100 */) {
return s == 'foo' && n == 1;
};
} }
} }

View File

@ -1,14 +1,4 @@
import { import {beforeEachProviders, beforeEach, ddescribe, describe, expect, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
beforeEachProviders,
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xit,
} from '@angular/core/testing/testing_internal';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {TestComponentBuilder} from '@angular/compiler/testing'; import {TestComponentBuilder} from '@angular/compiler/testing';
@ -20,95 +10,102 @@ export function main() {
beforeEachProviders(() => [{provide: NgLocalization, useClass: TestLocalizationMap}]); beforeEachProviders(() => [{provide: NgLocalization, useClass: TestLocalizationMap}]);
it('should display the template according to the exact value', it('should display the template according to the exact value',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div>' + [TestComponentBuilder, AsyncTestCompleter],
'<ul [ngPlural]="switchValue">' + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'<template ngPluralCase="=0"><li>you have no messages.</li></template>' + var template = '<div>' +
'<template ngPluralCase="=1"><li>you have one message.</li></template>' + '<ul [ngPlural]="switchValue">' +
'</ul></div>'; '<template ngPluralCase="=0"><li>you have no messages.</li></template>' +
'<template ngPluralCase="=1"><li>you have one message.</li></template>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.switchValue = 0; fixture.debugElement.componentInstance.switchValue = 0;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('you have no messages.'); expect(fixture.debugElement.nativeElement).toHaveText('you have no messages.');
fixture.debugElement.componentInstance.switchValue = 1; fixture.debugElement.componentInstance.switchValue = 1;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('you have one message.'); expect(fixture.debugElement.nativeElement).toHaveText('you have one message.');
async.done(); async.done();
}); });
})); }));
it('should display the template according to the category', it('should display the template according to the category',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
'<div>' + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'<ul [ngPlural]="switchValue">' + var template = '<div>' +
'<template ngPluralCase="few"><li>you have a few messages.</li></template>' + '<ul [ngPlural]="switchValue">' +
'<template ngPluralCase="many"><li>you have many messages.</li></template>' + '<template ngPluralCase="few"><li>you have a few messages.</li></template>' +
'</ul></div>'; '<template ngPluralCase="many"><li>you have many messages.</li></template>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.switchValue = 2; fixture.debugElement.componentInstance.switchValue = 2;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('you have a few messages.'); expect(fixture.debugElement.nativeElement)
.toHaveText('you have a few messages.');
fixture.debugElement.componentInstance.switchValue = 8; fixture.debugElement.componentInstance.switchValue = 8;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('you have many messages.'); expect(fixture.debugElement.nativeElement).toHaveText('you have many messages.');
async.done(); async.done();
}); });
})); }));
it('should default to other when no matches are found', it('should default to other when no matches are found',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
'<div>' + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'<ul [ngPlural]="switchValue">' + var template = '<div>' +
'<template ngPluralCase="few"><li>you have a few messages.</li></template>' + '<ul [ngPlural]="switchValue">' +
'<template ngPluralCase="other"><li>default message.</li></template>' + '<template ngPluralCase="few"><li>you have a few messages.</li></template>' +
'</ul></div>'; '<template ngPluralCase="other"><li>default message.</li></template>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.switchValue = 100; fixture.debugElement.componentInstance.switchValue = 100;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('default message.'); expect(fixture.debugElement.nativeElement).toHaveText('default message.');
async.done(); async.done();
}); });
})); }));
it('should prioritize value matches over category matches', it('should prioritize value matches over category matches',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
'<div>' + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'<ul [ngPlural]="switchValue">' + var template = '<div>' +
'<template ngPluralCase="few"><li>you have a few messages.</li></template>' + '<ul [ngPlural]="switchValue">' +
'<template ngPluralCase="=2">you have two messages.</template>' + '<template ngPluralCase="few"><li>you have a few messages.</li></template>' +
'</ul></div>'; '<template ngPluralCase="=2">you have two messages.</template>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.switchValue = 2; fixture.debugElement.componentInstance.switchValue = 2;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('you have two messages.'); expect(fixture.debugElement.nativeElement).toHaveText('you have two messages.');
fixture.debugElement.componentInstance.switchValue = 3; fixture.debugElement.componentInstance.switchValue = 3;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('you have a few messages.'); expect(fixture.debugElement.nativeElement)
.toHaveText('you have a few messages.');
async.done(); async.done();
}); });
})); }));
}); });
} }

View File

@ -1,15 +1,4 @@
import { import {beforeEach, beforeEachProviders, ddescribe, xdescribe, describe, expect, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
beforeEach,
beforeEachProviders,
ddescribe,
xdescribe,
describe,
expect,
iit,
inject,
it,
xit,
} from '@angular/core/testing/testing_internal';
import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing'; import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
@ -24,128 +13,141 @@ export function main() {
describe('binding to CSS styles', () => { describe('binding to CSS styles', () => {
it('should add styles specified in an object literal', it('should add styles specified in an object literal',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div [ngStyle]="{'max-width': '40px'}"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div [ngStyle]="{'max-width': '40px'}"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM().getStyle(
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'max-width')) fixture.debugElement.children[0].nativeElement, 'max-width'))
.toEqual('40px'); .toEqual('40px');
async.done(); async.done();
}); });
})); }));
it('should add and change styles specified in an object expression', it('should add and change styles specified in an object expression',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div [ngStyle]="expr"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div [ngStyle]="expr"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
var expr: Map<string, any>; var expr: Map<string, any>;
fixture.debugElement.componentInstance.expr = {'max-width': '40px'}; fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM().getStyle(
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'max-width')) fixture.debugElement.children[0].nativeElement, 'max-width'))
.toEqual('40px'); .toEqual('40px');
expr = fixture.debugElement.componentInstance.expr; expr = fixture.debugElement.componentInstance.expr;
(expr as any /** TODO #9100 */)['max-width'] = '30%'; (expr as any /** TODO #9100 */)['max-width'] = '30%';
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM().getStyle(
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'max-width')) fixture.debugElement.children[0].nativeElement, 'max-width'))
.toEqual('30%'); .toEqual('30%');
async.done(); async.done();
}); });
})); }));
it('should remove styles when deleting a key in an object expression', it('should remove styles when deleting a key in an object expression',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div [ngStyle]="expr"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div [ngStyle]="expr"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.expr = {'max-width': '40px'}; fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM().getStyle(
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'max-width')) fixture.debugElement.children[0].nativeElement, 'max-width'))
.toEqual('40px'); .toEqual('40px');
StringMapWrapper.delete(fixture.debugElement.componentInstance.expr, 'max-width'); StringMapWrapper.delete(
fixture.detectChanges(); fixture.debugElement.componentInstance.expr, 'max-width');
expect( fixture.detectChanges();
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'max-width')) expect(getDOM().getStyle(
.toEqual(''); fixture.debugElement.children[0].nativeElement, 'max-width'))
.toEqual('');
async.done(); async.done();
}); });
})); }));
it('should co-operate with the style attribute', it('should co-operate with the style attribute',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div style="font-size: 12px" [ngStyle]="expr"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div style="font-size: 12px" [ngStyle]="expr"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.expr = {'max-width': '40px'}; fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM().getStyle(
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'max-width')) fixture.debugElement.children[0].nativeElement, 'max-width'))
.toEqual('40px'); .toEqual('40px');
expect( expect(getDOM().getStyle(
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'font-size')) fixture.debugElement.children[0].nativeElement, 'font-size'))
.toEqual('12px'); .toEqual('12px');
StringMapWrapper.delete(fixture.debugElement.componentInstance.expr, 'max-width'); StringMapWrapper.delete(
fixture.detectChanges(); fixture.debugElement.componentInstance.expr, 'max-width');
expect( fixture.detectChanges();
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'max-width')) expect(getDOM().getStyle(
.toEqual(''); fixture.debugElement.children[0].nativeElement, 'max-width'))
expect( .toEqual('');
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'font-size')) expect(getDOM().getStyle(
.toEqual('12px'); fixture.debugElement.children[0].nativeElement, 'font-size'))
.toEqual('12px');
async.done(); async.done();
}); });
})); }));
it('should co-operate with the style.[styleName]="expr" special-case in the compiler', it('should co-operate with the style.[styleName]="expr" special-case in the compiler',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<div [style.font-size.px]="12" [ngStyle]="expr"></div>`; [TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var template = `<div [style.font-size.px]="12" [ngStyle]="expr"></div>`;
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.expr = {'max-width': '40px'}; fixture.debugElement.componentInstance.expr = {'max-width': '40px'};
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM().getStyle(
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'max-width')) fixture.debugElement.children[0].nativeElement, 'max-width'))
.toEqual('40px'); .toEqual('40px');
expect( expect(getDOM().getStyle(
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'font-size')) fixture.debugElement.children[0].nativeElement, 'font-size'))
.toEqual('12px'); .toEqual('12px');
StringMapWrapper.delete(fixture.debugElement.componentInstance.expr, 'max-width'); StringMapWrapper.delete(
expect( fixture.debugElement.componentInstance.expr, 'max-width');
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'font-size')) expect(getDOM().getStyle(
.toEqual('12px'); fixture.debugElement.children[0].nativeElement, 'font-size'))
.toEqual('12px');
fixture.detectChanges(); fixture.detectChanges();
expect( expect(getDOM().getStyle(
getDOM().getStyle(fixture.debugElement.children[0].nativeElement, 'max-width')) fixture.debugElement.children[0].nativeElement, 'max-width'))
.toEqual(''); .toEqual('');
async.done(); async.done();
}); });
})); }));
}) })
} }

View File

@ -1,13 +1,4 @@
import { import {beforeEach, ddescribe, describe, expect, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xit,
} from '@angular/core/testing/testing_internal';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing'; import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing';
@ -18,127 +9,135 @@ export function main() {
describe('switch', () => { describe('switch', () => {
describe('switch value changes', () => { describe('switch value changes', () => {
it('should switch amongst when values', it('should switch amongst when values',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div>' + [TestComponentBuilder, AsyncTestCompleter],
'<ul [ngSwitch]="switchValue">' + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'<template ngSwitchWhen="a"><li>when a</li></template>' + var template = '<div>' +
'<template ngSwitchWhen="b"><li>when b</li></template>' + '<ul [ngSwitch]="switchValue">' +
'</ul></div>'; '<template ngSwitchWhen="a"><li>when a</li></template>' +
'<template ngSwitchWhen="b"><li>when b</li></template>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText(''); expect(fixture.debugElement.nativeElement).toHaveText('');
fixture.debugElement.componentInstance.switchValue = 'a'; fixture.debugElement.componentInstance.switchValue = 'a';
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when a'); expect(fixture.debugElement.nativeElement).toHaveText('when a');
fixture.debugElement.componentInstance.switchValue = 'b'; fixture.debugElement.componentInstance.switchValue = 'b';
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when b'); expect(fixture.debugElement.nativeElement).toHaveText('when b');
async.done(); async.done();
}); });
})); }));
it('should switch amongst when values with fallback to default', it('should switch amongst when values with fallback to default',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div>' + [TestComponentBuilder, AsyncTestCompleter],
'<ul [ngSwitch]="switchValue">' + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'<li template="ngSwitchWhen \'a\'">when a</li>' + var template = '<div>' +
'<li template="ngSwitchDefault">when default</li>' + '<ul [ngSwitch]="switchValue">' +
'</ul></div>'; '<li template="ngSwitchWhen \'a\'">when a</li>' +
'<li template="ngSwitchDefault">when default</li>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when default'); expect(fixture.debugElement.nativeElement).toHaveText('when default');
fixture.debugElement.componentInstance.switchValue = 'a'; fixture.debugElement.componentInstance.switchValue = 'a';
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when a'); expect(fixture.debugElement.nativeElement).toHaveText('when a');
fixture.debugElement.componentInstance.switchValue = 'b'; fixture.debugElement.componentInstance.switchValue = 'b';
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when default'); expect(fixture.debugElement.nativeElement).toHaveText('when default');
async.done(); async.done();
}); });
})); }));
it('should support multiple whens with the same value', it('should support multiple whens with the same value',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div>' + [TestComponentBuilder, AsyncTestCompleter],
'<ul [ngSwitch]="switchValue">' + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'<template ngSwitchWhen="a"><li>when a1;</li></template>' + var template = '<div>' +
'<template ngSwitchWhen="b"><li>when b1;</li></template>' + '<ul [ngSwitch]="switchValue">' +
'<template ngSwitchWhen="a"><li>when a2;</li></template>' + '<template ngSwitchWhen="a"><li>when a1;</li></template>' +
'<template ngSwitchWhen="b"><li>when b2;</li></template>' + '<template ngSwitchWhen="b"><li>when b1;</li></template>' +
'<template ngSwitchDefault><li>when default1;</li></template>' + '<template ngSwitchWhen="a"><li>when a2;</li></template>' +
'<template ngSwitchDefault><li>when default2;</li></template>' + '<template ngSwitchWhen="b"><li>when b2;</li></template>' +
'</ul></div>'; '<template ngSwitchDefault><li>when default1;</li></template>' +
'<template ngSwitchDefault><li>when default2;</li></template>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement) expect(fixture.debugElement.nativeElement)
.toHaveText('when default1;when default2;'); .toHaveText('when default1;when default2;');
fixture.debugElement.componentInstance.switchValue = 'a'; fixture.debugElement.componentInstance.switchValue = 'a';
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when a1;when a2;'); expect(fixture.debugElement.nativeElement).toHaveText('when a1;when a2;');
fixture.debugElement.componentInstance.switchValue = 'b'; fixture.debugElement.componentInstance.switchValue = 'b';
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when b1;when b2;'); expect(fixture.debugElement.nativeElement).toHaveText('when b1;when b2;');
async.done(); async.done();
}); });
})); }));
}); });
describe('when values changes', () => { describe('when values changes', () => {
it('should switch amongst when values', it('should switch amongst when values',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div>' + [TestComponentBuilder, AsyncTestCompleter],
'<ul [ngSwitch]="switchValue">' + (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
'<template [ngSwitchWhen]="when1"><li>when 1;</li></template>' + var template = '<div>' +
'<template [ngSwitchWhen]="when2"><li>when 2;</li></template>' + '<ul [ngSwitch]="switchValue">' +
'<template ngSwitchDefault><li>when default;</li></template>' + '<template [ngSwitchWhen]="when1"><li>when 1;</li></template>' +
'</ul></div>'; '<template [ngSwitchWhen]="when2"><li>when 2;</li></template>' +
'<template ngSwitchDefault><li>when default;</li></template>' +
'</ul></div>';
tcb.overrideTemplate(TestComponent, template) tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent) .createAsync(TestComponent)
.then((fixture) => { .then((fixture) => {
fixture.debugElement.componentInstance.when1 = 'a'; fixture.debugElement.componentInstance.when1 = 'a';
fixture.debugElement.componentInstance.when2 = 'b'; fixture.debugElement.componentInstance.when2 = 'b';
fixture.debugElement.componentInstance.switchValue = 'a'; fixture.debugElement.componentInstance.switchValue = 'a';
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when 1;'); expect(fixture.debugElement.nativeElement).toHaveText('when 1;');
fixture.debugElement.componentInstance.switchValue = 'b'; fixture.debugElement.componentInstance.switchValue = 'b';
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when 2;'); expect(fixture.debugElement.nativeElement).toHaveText('when 2;');
fixture.debugElement.componentInstance.switchValue = 'c'; fixture.debugElement.componentInstance.switchValue = 'c';
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when default;'); expect(fixture.debugElement.nativeElement).toHaveText('when default;');
fixture.debugElement.componentInstance.when1 = 'c'; fixture.debugElement.componentInstance.when1 = 'c';
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when 1;'); expect(fixture.debugElement.nativeElement).toHaveText('when 1;');
fixture.debugElement.componentInstance.when1 = 'd'; fixture.debugElement.componentInstance.when1 = 'd';
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText('when default;'); expect(fixture.debugElement.nativeElement).toHaveText('when default;');
async.done(); async.done();
}); });
})); }));
}); });
}); });
} }

View File

@ -1,13 +1,4 @@
import { import {beforeEach, ddescribe, describe, expect, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xit,
} from '@angular/core/testing/testing_internal';
import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing'; import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {Component, Directive, TemplateRef, ContentChildren, QueryList} from '@angular/core'; import {Component, Directive, TemplateRef, ContentChildren, QueryList} from '@angular/core';
@ -16,84 +7,93 @@ import {NgTemplateOutlet} from '@angular/common';
export function main() { export function main() {
describe('insert', () => { describe('insert', () => {
it('should do nothing if templateRef is null', it('should do nothing if templateRef is null',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<template [ngTemplateOutlet]="null"></template>`; [TestComponentBuilder, AsyncTestCompleter],
tcb.overrideTemplate(TestComponent, template) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.createAsync(TestComponent) var template = `<template [ngTemplateOutlet]="null"></template>`;
.then((fixture) => { tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
async.done(); async.done();
}); });
})); }));
it('should insert content specified by TemplateRef', it('should insert content specified by TemplateRef',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideTemplate(TestComponent, template) var template =
.createAsync(TestComponent) `<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
.then((fixture) => { tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
var refs = fixture.debugElement.children[0].references['refs']; var refs = fixture.debugElement.children[0].references['refs'];
fixture.componentInstance.currentTplRef = refs.tplRefs.first; fixture.componentInstance.currentTplRef = refs.tplRefs.first;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('foo'); expect(fixture.nativeElement).toHaveText('foo');
async.done(); async.done();
}); });
})); }));
it('should clear content if TemplateRef becomes null', it('should clear content if TemplateRef becomes null',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = [TestComponentBuilder, AsyncTestCompleter],
`<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`; (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideTemplate(TestComponent, template) var template =
.createAsync(TestComponent) `<tpl-refs #refs="tplRefs"><template>foo</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
.then((fixture) => { tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
var refs = fixture.debugElement.children[0].references['refs']; var refs = fixture.debugElement.children[0].references['refs'];
fixture.componentInstance.currentTplRef = refs.tplRefs.first; fixture.componentInstance.currentTplRef = refs.tplRefs.first;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('foo'); expect(fixture.nativeElement).toHaveText('foo');
fixture.componentInstance.currentTplRef = null; fixture.componentInstance.currentTplRef = null;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
async.done(); async.done();
}); });
})); }));
it('should swap content if TemplateRef changes', it('should swap content if TemplateRef changes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = `<tpl-refs #refs="tplRefs"><template>foo</template><template>bar</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`; [TestComponentBuilder, AsyncTestCompleter],
tcb.overrideTemplate(TestComponent, template) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.createAsync(TestComponent) var template =
.then((fixture) => { `<tpl-refs #refs="tplRefs"><template>foo</template><template>bar</template></tpl-refs><template [ngTemplateOutlet]="currentTplRef"></template>`;
tcb.overrideTemplate(TestComponent, template)
.createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges(); fixture.detectChanges();
var refs = fixture.debugElement.children[0].references['refs']; var refs = fixture.debugElement.children[0].references['refs'];
fixture.componentInstance.currentTplRef = refs.tplRefs.first; fixture.componentInstance.currentTplRef = refs.tplRefs.first;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('foo'); expect(fixture.nativeElement).toHaveText('foo');
fixture.componentInstance.currentTplRef = refs.tplRefs.last; fixture.componentInstance.currentTplRef = refs.tplRefs.last;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('bar'); expect(fixture.nativeElement).toHaveText('bar');
async.done(); async.done();
}); });
})); }));
}); });
} }

View File

@ -1,13 +1,4 @@
import { import {beforeEach, ddescribe, describe, expect, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xit,
} from '@angular/core/testing/testing_internal';
import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing'; import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {Component, Directive} from '@angular/core'; import {Component, Directive} from '@angular/core';
@ -17,45 +8,51 @@ import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
export function main() { export function main() {
describe('non-bindable', () => { describe('non-bindable', () => {
it('should not interpolate children', it('should not interpolate children',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div>{{text}}<span ngNonBindable>{{text}}</span></div>'; [TestComponentBuilder, AsyncTestCompleter],
tcb.overrideTemplate(TestComponent, template) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.createAsync(TestComponent) var template = '<div>{{text}}<span ngNonBindable>{{text}}</span></div>';
.then((fixture) => { tcb.overrideTemplate(TestComponent, template)
fixture.detectChanges(); .createAsync(TestComponent)
expect(fixture.debugElement.nativeElement).toHaveText('foo{{text}}'); .then((fixture) => {
async.done(); fixture.detectChanges();
}); expect(fixture.debugElement.nativeElement).toHaveText('foo{{text}}');
})); async.done();
});
}));
it('should ignore directives on child nodes', it('should ignore directives on child nodes',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div ngNonBindable><span id=child test-dec>{{text}}</span></div>'; [TestComponentBuilder, AsyncTestCompleter],
tcb.overrideTemplate(TestComponent, template) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.createAsync(TestComponent) var template = '<div ngNonBindable><span id=child test-dec>{{text}}</span></div>';
.then((fixture) => { tcb.overrideTemplate(TestComponent, template)
fixture.detectChanges(); .createAsync(TestComponent)
.then((fixture) => {
fixture.detectChanges();
// We must use getDOM().querySelector instead of fixture.query here // We must use getDOM().querySelector instead of fixture.query here
// since the elements inside are not compiled. // since the elements inside are not compiled.
var span = getDOM().querySelector(fixture.debugElement.nativeElement, '#child'); var span = getDOM().querySelector(fixture.debugElement.nativeElement, '#child');
expect(getDOM().hasClass(span, 'compiled')).toBeFalsy(); expect(getDOM().hasClass(span, 'compiled')).toBeFalsy();
async.done(); async.done();
}); });
})); }));
it('should trigger directives on the same node', it('should trigger directives on the same node',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => { inject(
var template = '<div><span id=child ngNonBindable test-dec>{{text}}</span></div>'; [TestComponentBuilder, AsyncTestCompleter],
tcb.overrideTemplate(TestComponent, template) (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
.createAsync(TestComponent) var template = '<div><span id=child ngNonBindable test-dec>{{text}}</span></div>';
.then((fixture) => { tcb.overrideTemplate(TestComponent, template)
fixture.detectChanges(); .createAsync(TestComponent)
var span = getDOM().querySelector(fixture.debugElement.nativeElement, '#child'); .then((fixture) => {
expect(getDOM().hasClass(span, 'compiled')).toBeTruthy(); fixture.detectChanges();
async.done(); var span = getDOM().querySelector(fixture.debugElement.nativeElement, '#child');
}); expect(getDOM().hasClass(span, 'compiled')).toBeTruthy();
})); async.done();
});
}));
}) })
} }

View File

@ -1,41 +1,10 @@
import { import {afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
inject
} from '@angular/core/testing/testing_internal';
import { import {fakeAsync, flushMicrotasks, Log, tick,} from '@angular/core/testing';
fakeAsync,
flushMicrotasks,
Log,
tick,
} from '@angular/core/testing';
import {SpyNgControl, SpyValueAccessor} from '../spies'; import {SpyNgControl, SpyValueAccessor} from '../spies';
import { import {ControlGroup, Control, NgControlName, NgControlGroup, NgFormModel, ControlValueAccessor, Validators, NgForm, NgModel, NgFormControl, NgControl, DefaultValueAccessor, CheckboxControlValueAccessor, SelectControlValueAccessor, Validator} from '@angular/common';
ControlGroup,
Control,
NgControlName,
NgControlGroup,
NgFormModel,
ControlValueAccessor,
Validators,
NgForm,
NgModel,
NgFormControl,
NgControl,
DefaultValueAccessor,
CheckboxControlValueAccessor,
SelectControlValueAccessor,
Validator
} from '@angular/common';
import {selectValueAccessor, composeValidators} from '@angular/common/src/forms-deprecated/directives/shared'; import {selectValueAccessor, composeValidators} from '@angular/common/src/forms-deprecated/directives/shared';
@ -53,13 +22,13 @@ class DummyControlValueAccessor implements ControlValueAccessor {
} }
class CustomValidatorDirective implements Validator { class CustomValidatorDirective implements Validator {
validate(c: Control): {[key: string]: any} { return {"custom": true}; } validate(c: Control): {[key: string]: any} { return {'custom': true}; }
} }
function asyncValidator(expected: any /** TODO #9100 */, timeout = 0) { function asyncValidator(expected: any /** TODO #9100 */, timeout = 0) {
return (c: any /** TODO #9100 */) => { return (c: any /** TODO #9100 */) => {
var completer = PromiseWrapper.completer(); var completer = PromiseWrapper.completer();
var res = c.value != expected ? {"async": true} : null; var res = c.value != expected ? {'async': true} : null;
if (timeout == 0) { if (timeout == 0) {
completer.resolve(res); completer.resolve(res);
} else { } else {
@ -70,71 +39,73 @@ function asyncValidator(expected: any /** TODO #9100 */, timeout = 0) {
} }
export function main() { export function main() {
describe("Form Directives", () => { describe('Form Directives', () => {
var defaultAccessor: DefaultValueAccessor; var defaultAccessor: DefaultValueAccessor;
beforeEach(() => { defaultAccessor = new DefaultValueAccessor(null, null); }); beforeEach(() => { defaultAccessor = new DefaultValueAccessor(null, null); });
describe("shared", () => { describe('shared', () => {
describe("selectValueAccessor", () => { describe('selectValueAccessor', () => {
var dir: NgControl; var dir: NgControl;
beforeEach(() => { dir = <any>new SpyNgControl(); }); beforeEach(() => { dir = <any>new SpyNgControl(); });
it("should throw when given an empty array", it('should throw when given an empty array',
() => { expect(() => selectValueAccessor(dir, [])).toThrowError(); }); () => { expect(() => selectValueAccessor(dir, [])).toThrowError(); });
it("should return the default value accessor when no other provided", it('should return the default value accessor when no other provided',
() => { 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', () => {
var checkboxAccessor = new CheckboxControlValueAccessor(null, null); var checkboxAccessor = new CheckboxControlValueAccessor(null, null);
expect(selectValueAccessor(dir, [defaultAccessor, checkboxAccessor])) expect(selectValueAccessor(dir, [
.toEqual(checkboxAccessor); defaultAccessor, checkboxAccessor
])).toEqual(checkboxAccessor);
}); });
it("should return select accessor when provided", () => { it('should return select accessor when provided', () => {
var selectAccessor = new SelectControlValueAccessor(null, null); var selectAccessor = new SelectControlValueAccessor(null, null);
expect(selectValueAccessor(dir, [defaultAccessor, selectAccessor])) expect(selectValueAccessor(dir, [
.toEqual(selectAccessor); defaultAccessor, selectAccessor
])).toEqual(selectAccessor);
}); });
it("should throw when more than one build-in accessor is provided", () => { it('should throw when more than one build-in accessor is provided', () => {
var checkboxAccessor = new CheckboxControlValueAccessor(null, null); var checkboxAccessor = new CheckboxControlValueAccessor(null, null);
var selectAccessor = new SelectControlValueAccessor(null, null); var 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', () => {
var customAccessor = new SpyValueAccessor(); var customAccessor = new SpyValueAccessor();
var checkboxAccessor = new CheckboxControlValueAccessor(null, null); var 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 throw when more than one custom accessor is provided", () => { it('should throw when more than one custom accessor is provided', () => {
var customAccessor: ControlValueAccessor = <any>new SpyValueAccessor(); var customAccessor: ControlValueAccessor = <any>new SpyValueAccessor();
expect(() => selectValueAccessor(dir, [customAccessor, customAccessor])).toThrowError(); expect(() => selectValueAccessor(dir, [customAccessor, customAccessor])).toThrowError();
}); });
}); });
describe("composeValidators", () => { describe('composeValidators', () => {
it("should compose functions", () => { it('should compose functions', () => {
var dummy1 = (_: any /** TODO #9100 */) => ({"dummy1": true}); var dummy1 = (_: any /** TODO #9100 */) => ({'dummy1': true});
var dummy2 = (_: any /** TODO #9100 */) => ({"dummy2": true}); var dummy2 = (_: any /** TODO #9100 */) => ({'dummy2': true});
var v = composeValidators([dummy1, dummy2]); var v = composeValidators([dummy1, dummy2]);
expect(v(new Control(""))).toEqual({"dummy1": true, "dummy2": true}); expect(v(new Control(''))).toEqual({'dummy1': true, 'dummy2': true});
}); });
it("should compose validator directives", () => { it('should compose validator directives', () => {
var dummy1 = (_: any /** TODO #9100 */) => ({"dummy1": true}); var dummy1 = (_: any /** TODO #9100 */) => ({'dummy1': true});
var v = composeValidators([dummy1, new CustomValidatorDirective()]); var v = composeValidators([dummy1, new CustomValidatorDirective()]);
expect(v(new Control(""))).toEqual({"dummy1": true, "custom": true}); expect(v(new Control(''))).toEqual({'dummy1': true, 'custom': true});
}); });
}); });
}); });
describe("NgFormModel", () => { describe('NgFormModel', () => {
var form: any /** TODO #9100 */; var form: any /** TODO #9100 */;
var formModel: ControlGroup; var formModel: ControlGroup;
var loginControlDir: any /** TODO #9100 */; var loginControlDir: any /** TODO #9100 */;
@ -142,19 +113,19 @@ export function main() {
beforeEach(() => { beforeEach(() => {
form = new NgFormModel([], []); form = new NgFormModel([], []);
formModel = new ControlGroup({ formModel = new ControlGroup({
"login": new Control(), 'login': new Control(),
"passwords": 'passwords':
new ControlGroup({"password": new Control(), "passwordConfirm": new Control()}) new ControlGroup({'password': new Control(), 'passwordConfirm': new Control()})
}); });
form.form = formModel; form.form = formModel;
loginControlDir = new NgControlName(form, [Validators.required], loginControlDir = new NgControlName(
[asyncValidator("expected")], [defaultAccessor]); form, [Validators.required], [asyncValidator('expected')], [defaultAccessor]);
loginControlDir.name = "login"; loginControlDir.name = 'login';
loginControlDir.valueAccessor = new DummyControlValueAccessor(); loginControlDir.valueAccessor = new DummyControlValueAccessor();
}); });
it("should reexport control properties", () => { it('should reexport control properties', () => {
expect(form.control).toBe(formModel); expect(form.control).toBe(formModel);
expect(form.value).toBe(formModel.value); expect(form.value).toBe(formModel.value);
expect(form.valid).toBe(formModel.valid); expect(form.valid).toBe(formModel.valid);
@ -165,130 +136,132 @@ export function main() {
expect(form.untouched).toBe(formModel.untouched); expect(form.untouched).toBe(formModel.untouched);
}); });
describe("addControl", () => { describe('addControl', () => {
it("should throw when no control found", () => { it('should throw when no control found', () => {
var dir = new NgControlName(form, null, null, [defaultAccessor]); var dir = new NgControlName(form, null, null, [defaultAccessor]);
dir.name = "invalidName"; dir.name = 'invalidName';
expect(() => form.addControl(dir)) expect(() => form.addControl(dir))
.toThrowError(new RegExp("Cannot find control 'invalidName'")); .toThrowError(new RegExp('Cannot find control \'invalidName\''));
}); });
it("should throw when no value accessor", () => { it('should throw when no value accessor', () => {
var dir = new NgControlName(form, null, null, null); var dir = new NgControlName(form, null, null, null);
dir.name = "login"; dir.name = 'login';
expect(() => form.addControl(dir)) expect(() => form.addControl(dir))
.toThrowError(new RegExp("No value accessor for 'login'")); .toThrowError(new RegExp('No value accessor for \'login\''));
}); });
it("should set up validators", fakeAsync(() => { it('should set up validators', fakeAsync(() => {
form.addControl(loginControlDir); form.addControl(loginControlDir);
// sync validators are set // sync validators are set
expect(formModel.hasError("required", ["login"])).toBe(true); expect(formModel.hasError('required', ['login'])).toBe(true);
expect(formModel.hasError("async", ["login"])).toBe(false); expect(formModel.hasError('async', ['login'])).toBe(false);
(<Control>formModel.find(["login"])).updateValue("invalid value"); (<Control>formModel.find(['login'])).updateValue('invalid value');
// sync validator passes, running async validators // sync validator passes, running async validators
expect(formModel.pending).toBe(true); expect(formModel.pending).toBe(true);
tick(); tick();
expect(formModel.hasError("required", ["login"])).toBe(false); expect(formModel.hasError('required', ['login'])).toBe(false);
expect(formModel.hasError("async", ["login"])).toBe(true); expect(formModel.hasError('async', ['login'])).toBe(true);
})); }));
it("should write value to the DOM", () => { it('should write value to the DOM', () => {
(<Control>formModel.find(["login"])).updateValue("initValue"); (<Control>formModel.find(['login'])).updateValue('initValue');
form.addControl(loginControlDir); form.addControl(loginControlDir);
expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual("initValue"); expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual('initValue');
}); });
it("should add the directive to the list of directives included in the form", () => { it('should add the directive to the list of directives included in the form', () => {
form.addControl(loginControlDir); form.addControl(loginControlDir);
expect(form.directives).toEqual([loginControlDir]); expect(form.directives).toEqual([loginControlDir]);
}); });
}); });
describe("addControlGroup", () => { describe('addControlGroup', () => {
var matchingPasswordsValidator = (g: any /** TODO #9100 */) => { var matchingPasswordsValidator = (g: any /** TODO #9100 */) => {
if (g.controls["password"].value != g.controls["passwordConfirm"].value) { if (g.controls['password'].value != g.controls['passwordConfirm'].value) {
return {"differentPasswords": true}; return {'differentPasswords': true};
} else { } else {
return null; return null;
} }
}; };
it("should set up validator", fakeAsync(() => { it('should set up validator', fakeAsync(() => {
var group = new NgControlGroup(form, [matchingPasswordsValidator], var group = new NgControlGroup(
[asyncValidator('expected')]); form, [matchingPasswordsValidator], [asyncValidator('expected')]);
group.name = "passwords"; group.name = 'passwords';
form.addControlGroup(group); form.addControlGroup(group);
(<Control>formModel.find(["passwords", "password"])).updateValue("somePassword"); (<Control>formModel.find(['passwords', 'password'])).updateValue('somePassword');
(<Control>formModel.find(["passwords", "passwordConfirm"])) (<Control>formModel.find([
.updateValue("someOtherPassword"); 'passwords', 'passwordConfirm'
])).updateValue('someOtherPassword');
// sync validators are set // sync validators are set
expect(formModel.hasError("differentPasswords", ["passwords"])).toEqual(true); expect(formModel.hasError('differentPasswords', ['passwords'])).toEqual(true);
(<Control>formModel.find(["passwords", "passwordConfirm"])) (<Control>formModel.find([
.updateValue("somePassword"); 'passwords', 'passwordConfirm'
])).updateValue('somePassword');
// sync validators pass, running async validators // sync validators pass, running async validators
expect(formModel.pending).toBe(true); expect(formModel.pending).toBe(true);
tick(); tick();
expect(formModel.hasError("async", ["passwords"])).toBe(true); expect(formModel.hasError('async', ['passwords'])).toBe(true);
})); }));
}); });
describe("removeControl", () => { describe('removeControl', () => {
it("should remove the directive to the list of directives included in the form", () => { it('should remove the directive to the list of directives included in the form', () => {
form.addControl(loginControlDir); form.addControl(loginControlDir);
form.removeControl(loginControlDir); form.removeControl(loginControlDir);
expect(form.directives).toEqual([]); expect(form.directives).toEqual([]);
}); });
}); });
describe("ngOnChanges", () => { describe('ngOnChanges', () => {
it("should update dom values of all the directives", () => { it('should update dom values of all the directives', () => {
form.addControl(loginControlDir); form.addControl(loginControlDir);
(<Control>formModel.find(["login"])).updateValue("new value"); (<Control>formModel.find(['login'])).updateValue('new value');
form.ngOnChanges({}); form.ngOnChanges({});
expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual("new value"); expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual('new value');
}); });
it("should set up a sync validator", () => { it('should set up a sync validator', () => {
var formValidator = (c: any /** TODO #9100 */) => ({"custom": true}); var formValidator = (c: any /** TODO #9100 */) => ({'custom': true});
var f = new NgFormModel([formValidator], []); var f = new NgFormModel([formValidator], []);
f.form = formModel; f.form = formModel;
f.ngOnChanges({"form": new SimpleChange(null, null)}); f.ngOnChanges({'form': new SimpleChange(null, null)});
expect(formModel.errors).toEqual({"custom": true}); expect(formModel.errors).toEqual({'custom': true});
}); });
it("should set up an async validator", fakeAsync(() => { it('should set up an async validator', fakeAsync(() => {
var f = new NgFormModel([], [asyncValidator("expected")]); var f = new NgFormModel([], [asyncValidator('expected')]);
f.form = formModel; f.form = formModel;
f.ngOnChanges({"form": new SimpleChange(null, null)}); f.ngOnChanges({'form': new SimpleChange(null, null)});
tick(); tick();
expect(formModel.errors).toEqual({"async": true}); expect(formModel.errors).toEqual({'async': true});
})); }));
}); });
}); });
describe("NgForm", () => { describe('NgForm', () => {
var form: any /** TODO #9100 */; var form: any /** TODO #9100 */;
var formModel: ControlGroup; var formModel: ControlGroup;
var loginControlDir: any /** TODO #9100 */; var loginControlDir: any /** TODO #9100 */;
@ -299,14 +272,14 @@ export function main() {
formModel = form.form; formModel = form.form;
personControlGroupDir = new NgControlGroup(form, [], []); personControlGroupDir = new NgControlGroup(form, [], []);
personControlGroupDir.name = "person"; personControlGroupDir.name = 'person';
loginControlDir = new NgControlName(personControlGroupDir, null, null, [defaultAccessor]); loginControlDir = new NgControlName(personControlGroupDir, null, null, [defaultAccessor]);
loginControlDir.name = "login"; loginControlDir.name = 'login';
loginControlDir.valueAccessor = new DummyControlValueAccessor(); loginControlDir.valueAccessor = new DummyControlValueAccessor();
}); });
it("should reexport control properties", () => { it('should reexport control properties', () => {
expect(form.control).toBe(formModel); expect(form.control).toBe(formModel);
expect(form.value).toBe(formModel.value); expect(form.value).toBe(formModel.value);
expect(form.valid).toBe(formModel.valid); expect(form.valid).toBe(formModel.valid);
@ -317,21 +290,21 @@ export function main() {
expect(form.untouched).toBe(formModel.untouched); expect(form.untouched).toBe(formModel.untouched);
}); });
describe("addControl & addControlGroup", () => { describe('addControl & addControlGroup', () => {
it("should create a control with the given name", fakeAsync(() => { it('should create a control with the given name', fakeAsync(() => {
form.addControlGroup(personControlGroupDir); form.addControlGroup(personControlGroupDir);
form.addControl(loginControlDir); form.addControl(loginControlDir);
flushMicrotasks(); flushMicrotasks();
expect(formModel.find(["person", "login"])).not.toBeNull; expect(formModel.find(['person', 'login'])).not.toBeNull;
})); }));
// should update the form's value and validity // should update the form's value and validity
}); });
describe("removeControl & removeControlGroup", () => { describe('removeControl & removeControlGroup', () => {
it("should remove control", fakeAsync(() => { it('should remove control', fakeAsync(() => {
form.addControlGroup(personControlGroupDir); form.addControlGroup(personControlGroupDir);
form.addControl(loginControlDir); form.addControl(loginControlDir);
@ -340,45 +313,45 @@ export function main() {
flushMicrotasks(); flushMicrotasks();
expect(formModel.find(["person"])).toBeNull(); expect(formModel.find(['person'])).toBeNull();
expect(formModel.find(["person", "login"])).toBeNull(); expect(formModel.find(['person', 'login'])).toBeNull();
})); }));
// should update the form's value and validity // should update the form's value and validity
}); });
it("should set up sync validator", fakeAsync(() => { it('should set up sync validator', fakeAsync(() => {
var formValidator = (c: any /** TODO #9100 */) => ({"custom": true}); var formValidator = (c: any /** TODO #9100 */) => ({'custom': true});
var f = new NgForm([formValidator], []); var f = new NgForm([formValidator], []);
tick(); tick();
expect(f.form.errors).toEqual({"custom": true}); expect(f.form.errors).toEqual({'custom': true});
})); }));
it("should set up async validator", fakeAsync(() => { it('should set up async validator', fakeAsync(() => {
var f = new NgForm([], [asyncValidator("expected")]); var f = new NgForm([], [asyncValidator('expected')]);
tick(); tick();
expect(f.form.errors).toEqual({"async": true}); expect(f.form.errors).toEqual({'async': true});
})); }));
}); });
describe("NgControlGroup", () => { describe('NgControlGroup', () => {
var formModel: any /** TODO #9100 */; var formModel: any /** TODO #9100 */;
var controlGroupDir: any /** TODO #9100 */; var controlGroupDir: any /** TODO #9100 */;
beforeEach(() => { beforeEach(() => {
formModel = new ControlGroup({"login": new Control(null)}); formModel = new ControlGroup({'login': new Control(null)});
var parent = new NgFormModel([], []); var parent = new NgFormModel([], []);
parent.form = new ControlGroup({"group": formModel}); parent.form = new ControlGroup({'group': formModel});
controlGroupDir = new NgControlGroup(parent, [], []); controlGroupDir = new NgControlGroup(parent, [], []);
controlGroupDir.name = "group"; controlGroupDir.name = 'group';
}); });
it("should reexport control properties", () => { it('should reexport control properties', () => {
expect(controlGroupDir.control).toBe(formModel); expect(controlGroupDir.control).toBe(formModel);
expect(controlGroupDir.value).toBe(formModel.value); expect(controlGroupDir.value).toBe(formModel.value);
expect(controlGroupDir.valid).toBe(formModel.valid); expect(controlGroupDir.valid).toBe(formModel.valid);
@ -390,7 +363,7 @@ export function main() {
}); });
}); });
describe("NgFormControl", () => { describe('NgFormControl', () => {
var controlDir: any /** TODO #9100 */; var controlDir: any /** TODO #9100 */;
var control: any /** TODO #9100 */; var control: any /** TODO #9100 */;
var checkProperties = function(control: any /** TODO #9100 */) { var checkProperties = function(control: any /** TODO #9100 */) {
@ -412,36 +385,36 @@ export function main() {
controlDir.form = control; controlDir.form = control;
}); });
it("should reexport control properties", () => { checkProperties(control); }); it('should reexport control properties', () => { checkProperties(control); });
it("should reexport new control properties", () => { it('should reexport new control properties', () => {
var newControl = new Control(null); var newControl = new Control(null);
controlDir.form = newControl; controlDir.form = newControl;
controlDir.ngOnChanges({"form": new SimpleChange(control, newControl)}); controlDir.ngOnChanges({'form': new SimpleChange(control, newControl)});
checkProperties(newControl); checkProperties(newControl);
}); });
it("should set up validator", () => { it('should set up validator', () => {
expect(control.valid).toBe(true); expect(control.valid).toBe(true);
// this will add the required validator and recalculate the validity // this will add the required validator and recalculate the validity
controlDir.ngOnChanges({"form": new SimpleChange(null, control)}); controlDir.ngOnChanges({'form': new SimpleChange(null, control)});
expect(control.valid).toBe(false); expect(control.valid).toBe(false);
}); });
}); });
describe("NgModel", () => { describe('NgModel', () => {
var ngModel: any /** TODO #9100 */; var ngModel: any /** TODO #9100 */;
beforeEach(() => { beforeEach(() => {
ngModel = ngModel =
new NgModel([Validators.required], [asyncValidator("expected")], [defaultAccessor]); new NgModel([Validators.required], [asyncValidator('expected')], [defaultAccessor]);
ngModel.valueAccessor = new DummyControlValueAccessor(); ngModel.valueAccessor = new DummyControlValueAccessor();
}); });
it("should reexport control properties", () => { it('should reexport control properties', () => {
var control = ngModel.control; var control = ngModel.control;
expect(ngModel.control).toBe(control); expect(ngModel.control).toBe(control);
expect(ngModel.value).toBe(control.value); expect(ngModel.value).toBe(control.value);
@ -453,34 +426,34 @@ export function main() {
expect(ngModel.untouched).toBe(control.untouched); expect(ngModel.untouched).toBe(control.untouched);
}); });
it("should set up validator", fakeAsync(() => { it('should set up validator', fakeAsync(() => {
// this will add the required validator and recalculate the validity // this will add the required validator and recalculate the validity
ngModel.ngOnChanges({}); ngModel.ngOnChanges({});
tick(); tick();
expect(ngModel.control.errors).toEqual({"required": true}); expect(ngModel.control.errors).toEqual({'required': true});
ngModel.control.updateValue("someValue"); ngModel.control.updateValue('someValue');
tick(); tick();
expect(ngModel.control.errors).toEqual({"async": true}); expect(ngModel.control.errors).toEqual({'async': true});
})); }));
}); });
describe("NgControlName", () => { describe('NgControlName', () => {
var formModel: any /** TODO #9100 */; var formModel: any /** TODO #9100 */;
var controlNameDir: any /** TODO #9100 */; var controlNameDir: any /** TODO #9100 */;
beforeEach(() => { beforeEach(() => {
formModel = new Control("name"); formModel = new Control('name');
var parent = new NgFormModel([], []); var parent = new NgFormModel([], []);
parent.form = new ControlGroup({"name": formModel}); parent.form = new ControlGroup({'name': formModel});
controlNameDir = new NgControlName(parent, [], [], [defaultAccessor]); controlNameDir = new NgControlName(parent, [], [], [defaultAccessor]);
controlNameDir.name = "name"; controlNameDir.name = 'name';
}); });
it("should reexport control properties", () => { it('should reexport control properties', () => {
expect(controlNameDir.control).toBe(formModel); expect(controlNameDir.control).toBe(formModel);
expect(controlNameDir.value).toBe(formModel.value); expect(controlNameDir.value).toBe(formModel.value);
expect(controlNameDir.valid).toBe(formModel.valid); expect(controlNameDir.valid).toBe(formModel.valid);

View File

@ -1,67 +1,59 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/core/testing/testing_internal';
import {Control, FormBuilder} from '@angular/common'; import {Control, FormBuilder} from '@angular/common';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {PromiseWrapper} from '../../src/facade/promise'; import {PromiseWrapper} from '../../src/facade/promise';
export function main() { export function main() {
function syncValidator(_: any /** TODO #9100 */): any /** TODO #9100 */ { return null; } function syncValidator(_: any /** TODO #9100 */): any /** TODO #9100 */ { return null; }
function asyncValidator(_: any /** TODO #9100 */) { return PromiseWrapper.resolve(null); } function asyncValidator(_: any /** TODO #9100 */) { return PromiseWrapper.resolve(null); }
describe("Form Builder", () => { describe('Form Builder', () => {
var b: any /** TODO #9100 */; var b: any /** TODO #9100 */;
beforeEach(() => { b = new FormBuilder(); }); beforeEach(() => { b = new FormBuilder(); });
it("should create controls from a value", () => { it('should create controls from a value', () => {
var g = b.group({"login": "some value"}); var g = b.group({'login': 'some value'});
expect(g.controls["login"].value).toEqual("some value"); expect(g.controls['login'].value).toEqual('some value');
}); });
it("should create controls from an array", () => { it('should create controls from an array', () => {
var g = b.group( var g = b.group(
{"login": ["some value"], "password": ["some value", syncValidator, asyncValidator]}); {'login': ['some value'], 'password': ['some value', syncValidator, asyncValidator]});
expect(g.controls["login"].value).toEqual("some value"); expect(g.controls['login'].value).toEqual('some value');
expect(g.controls["password"].value).toEqual("some value"); expect(g.controls['password'].value).toEqual('some value');
expect(g.controls["password"].validator).toEqual(syncValidator); expect(g.controls['password'].validator).toEqual(syncValidator);
expect(g.controls["password"].asyncValidator).toEqual(asyncValidator); expect(g.controls['password'].asyncValidator).toEqual(asyncValidator);
}); });
it("should use controls", () => { it('should use controls', () => {
var g = b.group({"login": b.control("some value", syncValidator, asyncValidator)}); var g = b.group({'login': b.control('some value', syncValidator, asyncValidator)});
expect(g.controls["login"].value).toEqual("some value"); expect(g.controls['login'].value).toEqual('some value');
expect(g.controls["login"].validator).toBe(syncValidator); expect(g.controls['login'].validator).toBe(syncValidator);
expect(g.controls["login"].asyncValidator).toBe(asyncValidator); expect(g.controls['login'].asyncValidator).toBe(asyncValidator);
}); });
it("should create groups with optional controls", () => { it('should create groups with optional controls', () => {
var g = b.group({"login": "some value"}, {"optionals": {"login": false}}); var g = b.group({'login': 'some value'}, {'optionals': {'login': false}});
expect(g.contains("login")).toEqual(false); expect(g.contains('login')).toEqual(false);
}); });
it("should create groups with a custom validator", () => { it('should create groups with a custom validator', () => {
var g = b.group({"login": "some value"}, var g = b.group(
{"validator": syncValidator, "asyncValidator": asyncValidator}); {'login': 'some value'}, {'validator': syncValidator, 'asyncValidator': asyncValidator});
expect(g.validator).toBe(syncValidator); expect(g.validator).toBe(syncValidator);
expect(g.asyncValidator).toBe(asyncValidator); expect(g.asyncValidator).toBe(asyncValidator);
}); });
it("should create control arrays", () => { it('should create control arrays', () => {
var c = b.control("three"); var c = b.control('three');
var a = b.array(["one", ["two", syncValidator], c, b.array(['four'])], syncValidator, var a = b.array(
asyncValidator); ['one', ['two', syncValidator], c, b.array(['four'])], syncValidator, asyncValidator);
expect(a.value).toEqual(['one', 'two', 'three', ['four']]); expect(a.value).toEqual(['one', 'two', 'three', ['four']]);
expect(a.validator).toBe(syncValidator); expect(a.validator).toBe(syncValidator);

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,9 @@
import { import {AbstractControl, Control, ControlArray, ControlGroup, Validators} from '@angular/common';
ddescribe, import {Log, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
describe, import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/core/testing/testing_internal';
import {fakeAsync, flushMicrotasks, Log, tick} from '@angular/core/testing';
import {ControlGroup, Control, Validators, AbstractControl, ControlArray} from '@angular/common';
import {PromiseWrapper} from '../../src/facade/promise';
import {EventEmitter, ObservableWrapper, TimerWrapper} from '../../src/facade/async'; import {EventEmitter, ObservableWrapper, TimerWrapper} from '../../src/facade/async';
import {PromiseWrapper} from '../../src/facade/promise';
export function main() { export function main() {
function validator(key: string, error: any) { function validator(key: string, error: any) {
@ -22,95 +14,98 @@ export function main() {
} }
} }
describe("Validators", () => { describe('Validators', () => {
describe("required", () => { describe('required', () => {
it("should error on an empty string", it('should error on an empty string',
() => { expect(Validators.required(new Control(""))).toEqual({"required": true}); }); () => { expect(Validators.required(new Control(''))).toEqual({'required': true}); });
it("should error on null", it('should error on null',
() => { expect(Validators.required(new Control(null))).toEqual({"required": true}); }); () => { expect(Validators.required(new Control(null))).toEqual({'required': true}); });
it("should not error on a non-empty string", it('should not error on a non-empty string',
() => { expect(Validators.required(new Control("not empty"))).toEqual(null); }); () => { expect(Validators.required(new Control('not empty'))).toEqual(null); });
it("should accept zero as valid", it('should accept zero as valid',
() => { expect(Validators.required(new Control(0))).toEqual(null); }); () => { expect(Validators.required(new Control(0))).toEqual(null); });
}); });
describe("minLength", () => { describe('minLength', () => {
it("should not error on an empty string", it('should not error on an empty string',
() => { expect(Validators.minLength(2)(new Control(""))).toEqual(null); }); () => { expect(Validators.minLength(2)(new Control(''))).toEqual(null); });
it("should not error on null", it('should not error on null',
() => { expect(Validators.minLength(2)(new Control(null))).toEqual(null); }); () => { expect(Validators.minLength(2)(new Control(null))).toEqual(null); });
it("should not error on valid strings", it('should not error on valid strings',
() => { expect(Validators.minLength(2)(new Control("aa"))).toEqual(null); }); () => { expect(Validators.minLength(2)(new Control('aa'))).toEqual(null); });
it("should error on short strings", () => { it('should error on short strings', () => {
expect(Validators.minLength(2)(new Control("a"))) expect(Validators.minLength(2)(new Control('a'))).toEqual({
.toEqual({"minlength": {"requiredLength": 2, "actualLength": 1}}); 'minlength': {'requiredLength': 2, 'actualLength': 1}
});
}); });
}); });
describe("maxLength", () => { describe('maxLength', () => {
it("should not error on an empty string", it('should not error on an empty string',
() => { expect(Validators.maxLength(2)(new Control(""))).toEqual(null); }); () => { expect(Validators.maxLength(2)(new Control(''))).toEqual(null); });
it("should not error on null", it('should not error on null',
() => { expect(Validators.maxLength(2)(new Control(null))).toEqual(null); }); () => { expect(Validators.maxLength(2)(new Control(null))).toEqual(null); });
it("should not error on valid strings", it('should not error on valid strings',
() => { expect(Validators.maxLength(2)(new Control("aa"))).toEqual(null); }); () => { expect(Validators.maxLength(2)(new Control('aa'))).toEqual(null); });
it("should error on long strings", () => { it('should error on long strings', () => {
expect(Validators.maxLength(2)(new Control("aaa"))) expect(Validators.maxLength(2)(new Control('aaa'))).toEqual({
.toEqual({"maxlength": {"requiredLength": 2, "actualLength": 3}}); 'maxlength': {'requiredLength': 2, 'actualLength': 3}
});
}); });
}); });
describe("pattern", () => { describe('pattern', () => {
it("should not error on an empty string", it('should not error on an empty string',
() => { expect(Validators.pattern("[a-zA-Z ]*")(new Control(""))).toEqual(null); }); () => { expect(Validators.pattern('[a-zA-Z ]*')(new Control(''))).toEqual(null); });
it("should not error on null", it('should not error on null',
() => { expect(Validators.pattern("[a-zA-Z ]*")(new Control(null))).toEqual(null); }); () => { expect(Validators.pattern('[a-zA-Z ]*')(new Control(null))).toEqual(null); });
it("should not error on valid strings", it('should not error on valid strings',
() => { expect(Validators.pattern("[a-zA-Z ]*")(new Control("aaAA"))).toEqual(null); }); () => { expect(Validators.pattern('[a-zA-Z ]*')(new Control('aaAA'))).toEqual(null); });
it("should error on failure to match string", () => { it('should error on failure to match string', () => {
expect(Validators.pattern("[a-zA-Z ]*")(new Control("aaa0"))) expect(Validators.pattern('[a-zA-Z ]*')(new Control('aaa0'))).toEqual({
.toEqual({"pattern": {"requiredPattern": "^[a-zA-Z ]*$", "actualValue": "aaa0"}}); 'pattern': {'requiredPattern': '^[a-zA-Z ]*$', 'actualValue': 'aaa0'}
});
}); });
}); });
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', () => {
var c = Validators.compose([validator("a", true), validator("b", true)]); var c = Validators.compose([validator('a', true), validator('b', true)]);
expect(c(new Control(""))).toEqual({"a": true, "b": true}); expect(c(new Control(''))).toEqual({'a': true, 'b': true});
}); });
it("should run validators left to right", () => { it('should run validators left to right', () => {
var c = Validators.compose([validator("a", 1), validator("a", 2)]); var c = Validators.compose([validator('a', 1), validator('a', 2)]);
expect(c(new Control(""))).toEqual({"a": 2}); expect(c(new Control(''))).toEqual({'a': 2});
}); });
it("should return null when no errors", () => { it('should return null when no errors', () => {
var c = Validators.compose([Validators.nullValidator, Validators.nullValidator]); var c = Validators.compose([Validators.nullValidator, Validators.nullValidator]);
expect(c(new Control(""))).toEqual(null); expect(c(new Control(''))).toEqual(null);
}); });
it("should ignore nulls", () => { it('should ignore nulls', () => {
var c = Validators.compose([null, Validators.required]); var c = Validators.compose([null, Validators.required]);
expect(c(new Control(""))).toEqual({"required": true}); expect(c(new Control(''))).toEqual({'required': true});
}); });
}); });
describe("composeAsync", () => { describe('composeAsync', () => {
function asyncValidator(expected: any /** TODO #9100 */, response: any /** TODO #9100 */) { function asyncValidator(expected: any /** TODO #9100 */, response: any /** TODO #9100 */) {
return (c: any /** TODO #9100 */) => { return (c: any /** TODO #9100 */) => {
var emitter = new EventEmitter(); var emitter = new EventEmitter();
@ -127,43 +122,42 @@ export function main() {
}; };
} }
it("should return null when given null", it('should return null when given null',
() => { expect(Validators.composeAsync(null)).toEqual(null); }); () => { expect(Validators.composeAsync(null)).toEqual(null); });
it("should collect errors from all the validators", fakeAsync(() => { it('should collect errors from all the validators', fakeAsync(() => {
var c = Validators.composeAsync([ var c = Validators.composeAsync([
asyncValidator("expected", {"one": true}), asyncValidator('expected', {'one': true}), asyncValidator('expected', {'two': true})
asyncValidator("expected", {"two": true})
]); ]);
var value: any /** TODO #9100 */ = null; var value: any /** TODO #9100 */ = null;
(<Promise<any>>c(new Control("invalid"))).then(v => value = v); (<Promise<any>>c(new Control('invalid'))).then(v => value = v);
tick(1); tick(1);
expect(value).toEqual({"one": true, "two": true}); expect(value).toEqual({'one': true, 'two': true});
})); }));
it("should return null when no errors", fakeAsync(() => { it('should return null when no errors', fakeAsync(() => {
var c = Validators.composeAsync([asyncValidator("expected", {"one": true})]); var c = Validators.composeAsync([asyncValidator('expected', {'one': true})]);
var value: any /** TODO #9100 */ = null; var value: any /** TODO #9100 */ = null;
(<Promise<any>>c(new Control("expected"))).then(v => value = v); (<Promise<any>>c(new Control('expected'))).then(v => value = v);
tick(1); tick(1);
expect(value).toEqual(null); expect(value).toEqual(null);
})); }));
it("should ignore nulls", fakeAsync(() => { it('should ignore nulls', fakeAsync(() => {
var c = Validators.composeAsync([asyncValidator("expected", {"one": true}), null]); var c = Validators.composeAsync([asyncValidator('expected', {'one': true}), null]);
var value: any /** TODO #9100 */ = null; var value: any /** TODO #9100 */ = null;
(<Promise<any>>c(new Control("invalid"))).then(v => value = v); (<Promise<any>>c(new Control('invalid'))).then(v => value = v);
tick(1); tick(1);
expect(value).toEqual({"one": true}); expect(value).toEqual({'one': true});
})); }));
}); });
}); });

View File

@ -1,41 +1,10 @@
import { import {afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
inject
} from '@angular/core/testing/testing_internal';
import { import {fakeAsync, flushMicrotasks, Log, tick,} from '@angular/core/testing';
fakeAsync,
flushMicrotasks,
Log,
tick,
} from '@angular/core/testing';
import {SpyNgControl, SpyValueAccessor} from '../spies'; import {SpyNgControl, SpyValueAccessor} from '../spies';
import { import {ControlGroup, Control, NgControlName, NgControlGroup, NgFormModel, ControlValueAccessor, Validators, NgForm, NgModel, NgFormControl, NgControl, DefaultValueAccessor, CheckboxControlValueAccessor, SelectControlValueAccessor, Validator} from '@angular/common/src/forms';
ControlGroup,
Control,
NgControlName,
NgControlGroup,
NgFormModel,
ControlValueAccessor,
Validators,
NgForm,
NgModel,
NgFormControl,
NgControl,
DefaultValueAccessor,
CheckboxControlValueAccessor,
SelectControlValueAccessor,
Validator
} from '@angular/common/src/forms';
import {selectValueAccessor, composeValidators} from '@angular/common/src/forms/directives/shared'; import {selectValueAccessor, composeValidators} from '@angular/common/src/forms/directives/shared';
@ -53,13 +22,13 @@ class DummyControlValueAccessor implements ControlValueAccessor {
} }
class CustomValidatorDirective implements Validator { class CustomValidatorDirective implements Validator {
validate(c: Control): {[key: string]: any} { return {"custom": true}; } validate(c: Control): {[key: string]: any} { return {'custom': true}; }
} }
function asyncValidator(expected: any /** TODO #9100 */, timeout = 0) { function asyncValidator(expected: any /** TODO #9100 */, timeout = 0) {
return (c: any /** TODO #9100 */) => { return (c: any /** TODO #9100 */) => {
var completer = PromiseWrapper.completer(); var completer = PromiseWrapper.completer();
var res = c.value != expected ? {"async": true} : null; var res = c.value != expected ? {'async': true} : null;
if (timeout == 0) { if (timeout == 0) {
completer.resolve(res); completer.resolve(res);
} else { } else {
@ -70,71 +39,73 @@ function asyncValidator(expected: any /** TODO #9100 */, timeout = 0) {
} }
export function main() { export function main() {
describe("Form Directives", () => { describe('Form Directives', () => {
var defaultAccessor: DefaultValueAccessor; var defaultAccessor: DefaultValueAccessor;
beforeEach(() => { defaultAccessor = new DefaultValueAccessor(null, null); }); beforeEach(() => { defaultAccessor = new DefaultValueAccessor(null, null); });
describe("shared", () => { describe('shared', () => {
describe("selectValueAccessor", () => { describe('selectValueAccessor', () => {
var dir: NgControl; var dir: NgControl;
beforeEach(() => { dir = <any>new SpyNgControl(); }); beforeEach(() => { dir = <any>new SpyNgControl(); });
it("should throw when given an empty array", it('should throw when given an empty array',
() => { expect(() => selectValueAccessor(dir, [])).toThrowError(); }); () => { expect(() => selectValueAccessor(dir, [])).toThrowError(); });
it("should return the default value accessor when no other provided", it('should return the default value accessor when no other provided',
() => { 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', () => {
var checkboxAccessor = new CheckboxControlValueAccessor(null, null); var checkboxAccessor = new CheckboxControlValueAccessor(null, null);
expect(selectValueAccessor(dir, [defaultAccessor, checkboxAccessor])) expect(selectValueAccessor(dir, [
.toEqual(checkboxAccessor); defaultAccessor, checkboxAccessor
])).toEqual(checkboxAccessor);
}); });
it("should return select accessor when provided", () => { it('should return select accessor when provided', () => {
var selectAccessor = new SelectControlValueAccessor(null, null); var selectAccessor = new SelectControlValueAccessor(null, null);
expect(selectValueAccessor(dir, [defaultAccessor, selectAccessor])) expect(selectValueAccessor(dir, [
.toEqual(selectAccessor); defaultAccessor, selectAccessor
])).toEqual(selectAccessor);
}); });
it("should throw when more than one build-in accessor is provided", () => { it('should throw when more than one build-in accessor is provided', () => {
var checkboxAccessor = new CheckboxControlValueAccessor(null, null); var checkboxAccessor = new CheckboxControlValueAccessor(null, null);
var selectAccessor = new SelectControlValueAccessor(null, null); var 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', () => {
var customAccessor = new SpyValueAccessor(); var customAccessor = new SpyValueAccessor();
var checkboxAccessor = new CheckboxControlValueAccessor(null, null); var 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 throw when more than one custom accessor is provided", () => { it('should throw when more than one custom accessor is provided', () => {
var customAccessor: ControlValueAccessor = <any>new SpyValueAccessor(); var customAccessor: ControlValueAccessor = <any>new SpyValueAccessor();
expect(() => selectValueAccessor(dir, [customAccessor, customAccessor])).toThrowError(); expect(() => selectValueAccessor(dir, [customAccessor, customAccessor])).toThrowError();
}); });
}); });
describe("composeValidators", () => { describe('composeValidators', () => {
it("should compose functions", () => { it('should compose functions', () => {
var dummy1 = (_: any /** TODO #9100 */) => ({"dummy1": true}); var dummy1 = (_: any /** TODO #9100 */) => ({'dummy1': true});
var dummy2 = (_: any /** TODO #9100 */) => ({"dummy2": true}); var dummy2 = (_: any /** TODO #9100 */) => ({'dummy2': true});
var v = composeValidators([dummy1, dummy2]); var v = composeValidators([dummy1, dummy2]);
expect(v(new Control(""))).toEqual({"dummy1": true, "dummy2": true}); expect(v(new Control(''))).toEqual({'dummy1': true, 'dummy2': true});
}); });
it("should compose validator directives", () => { it('should compose validator directives', () => {
var dummy1 = (_: any /** TODO #9100 */) => ({"dummy1": true}); var dummy1 = (_: any /** TODO #9100 */) => ({'dummy1': true});
var v = composeValidators([dummy1, new CustomValidatorDirective()]); var v = composeValidators([dummy1, new CustomValidatorDirective()]);
expect(v(new Control(""))).toEqual({"dummy1": true, "custom": true}); expect(v(new Control(''))).toEqual({'dummy1': true, 'custom': true});
}); });
}); });
}); });
describe("NgFormModel", () => { describe('NgFormModel', () => {
var form: any /** TODO #9100 */; var form: any /** TODO #9100 */;
var formModel: ControlGroup; var formModel: ControlGroup;
var loginControlDir: any /** TODO #9100 */; var loginControlDir: any /** TODO #9100 */;
@ -142,19 +113,19 @@ export function main() {
beforeEach(() => { beforeEach(() => {
form = new NgFormModel([], []); form = new NgFormModel([], []);
formModel = new ControlGroup({ formModel = new ControlGroup({
"login": new Control(), 'login': new Control(),
"passwords": 'passwords':
new ControlGroup({"password": new Control(), "passwordConfirm": new Control()}) new ControlGroup({'password': new Control(), 'passwordConfirm': new Control()})
}); });
form.form = formModel; form.form = formModel;
loginControlDir = new NgControlName(form, [Validators.required], loginControlDir = new NgControlName(
[asyncValidator("expected")], [defaultAccessor]); form, [Validators.required], [asyncValidator('expected')], [defaultAccessor]);
loginControlDir.name = "login"; loginControlDir.name = 'login';
loginControlDir.valueAccessor = new DummyControlValueAccessor(); loginControlDir.valueAccessor = new DummyControlValueAccessor();
}); });
it("should reexport control properties", () => { it('should reexport control properties', () => {
expect(form.control).toBe(formModel); expect(form.control).toBe(formModel);
expect(form.value).toBe(formModel.value); expect(form.value).toBe(formModel.value);
expect(form.valid).toBe(formModel.valid); expect(form.valid).toBe(formModel.valid);
@ -165,130 +136,132 @@ export function main() {
expect(form.untouched).toBe(formModel.untouched); expect(form.untouched).toBe(formModel.untouched);
}); });
describe("addControl", () => { describe('addControl', () => {
it("should throw when no control found", () => { it('should throw when no control found', () => {
var dir = new NgControlName(form, null, null, [defaultAccessor]); var dir = new NgControlName(form, null, null, [defaultAccessor]);
dir.name = "invalidName"; dir.name = 'invalidName';
expect(() => form.addControl(dir)) expect(() => form.addControl(dir))
.toThrowError(new RegExp("Cannot find control 'invalidName'")); .toThrowError(new RegExp('Cannot find control \'invalidName\''));
}); });
it("should throw when no value accessor", () => { it('should throw when no value accessor', () => {
var dir = new NgControlName(form, null, null, null); var dir = new NgControlName(form, null, null, null);
dir.name = "login"; dir.name = 'login';
expect(() => form.addControl(dir)) expect(() => form.addControl(dir))
.toThrowError(new RegExp("No value accessor for 'login'")); .toThrowError(new RegExp('No value accessor for \'login\''));
}); });
it("should set up validators", fakeAsync(() => { it('should set up validators', fakeAsync(() => {
form.addControl(loginControlDir); form.addControl(loginControlDir);
// sync validators are set // sync validators are set
expect(formModel.hasError("required", ["login"])).toBe(true); expect(formModel.hasError('required', ['login'])).toBe(true);
expect(formModel.hasError("async", ["login"])).toBe(false); expect(formModel.hasError('async', ['login'])).toBe(false);
(<Control>formModel.find(["login"])).updateValue("invalid value"); (<Control>formModel.find(['login'])).updateValue('invalid value');
// sync validator passes, running async validators // sync validator passes, running async validators
expect(formModel.pending).toBe(true); expect(formModel.pending).toBe(true);
tick(); tick();
expect(formModel.hasError("required", ["login"])).toBe(false); expect(formModel.hasError('required', ['login'])).toBe(false);
expect(formModel.hasError("async", ["login"])).toBe(true); expect(formModel.hasError('async', ['login'])).toBe(true);
})); }));
it("should write value to the DOM", () => { it('should write value to the DOM', () => {
(<Control>formModel.find(["login"])).updateValue("initValue"); (<Control>formModel.find(['login'])).updateValue('initValue');
form.addControl(loginControlDir); form.addControl(loginControlDir);
expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual("initValue"); expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual('initValue');
}); });
it("should add the directive to the list of directives included in the form", () => { it('should add the directive to the list of directives included in the form', () => {
form.addControl(loginControlDir); form.addControl(loginControlDir);
expect(form.directives).toEqual([loginControlDir]); expect(form.directives).toEqual([loginControlDir]);
}); });
}); });
describe("addControlGroup", () => { describe('addControlGroup', () => {
var matchingPasswordsValidator = (g: any /** TODO #9100 */) => { var matchingPasswordsValidator = (g: any /** TODO #9100 */) => {
if (g.controls["password"].value != g.controls["passwordConfirm"].value) { if (g.controls['password'].value != g.controls['passwordConfirm'].value) {
return {"differentPasswords": true}; return {'differentPasswords': true};
} else { } else {
return null; return null;
} }
}; };
it("should set up validator", fakeAsync(() => { it('should set up validator', fakeAsync(() => {
var group = new NgControlGroup(form, [matchingPasswordsValidator], var group = new NgControlGroup(
[asyncValidator('expected')]); form, [matchingPasswordsValidator], [asyncValidator('expected')]);
group.name = "passwords"; group.name = 'passwords';
form.addControlGroup(group); form.addControlGroup(group);
(<Control>formModel.find(["passwords", "password"])).updateValue("somePassword"); (<Control>formModel.find(['passwords', 'password'])).updateValue('somePassword');
(<Control>formModel.find(["passwords", "passwordConfirm"])) (<Control>formModel.find([
.updateValue("someOtherPassword"); 'passwords', 'passwordConfirm'
])).updateValue('someOtherPassword');
// sync validators are set // sync validators are set
expect(formModel.hasError("differentPasswords", ["passwords"])).toEqual(true); expect(formModel.hasError('differentPasswords', ['passwords'])).toEqual(true);
(<Control>formModel.find(["passwords", "passwordConfirm"])) (<Control>formModel.find([
.updateValue("somePassword"); 'passwords', 'passwordConfirm'
])).updateValue('somePassword');
// sync validators pass, running async validators // sync validators pass, running async validators
expect(formModel.pending).toBe(true); expect(formModel.pending).toBe(true);
tick(); tick();
expect(formModel.hasError("async", ["passwords"])).toBe(true); expect(formModel.hasError('async', ['passwords'])).toBe(true);
})); }));
}); });
describe("removeControl", () => { describe('removeControl', () => {
it("should remove the directive to the list of directives included in the form", () => { it('should remove the directive to the list of directives included in the form', () => {
form.addControl(loginControlDir); form.addControl(loginControlDir);
form.removeControl(loginControlDir); form.removeControl(loginControlDir);
expect(form.directives).toEqual([]); expect(form.directives).toEqual([]);
}); });
}); });
describe("ngOnChanges", () => { describe('ngOnChanges', () => {
it("should update dom values of all the directives", () => { it('should update dom values of all the directives', () => {
form.addControl(loginControlDir); form.addControl(loginControlDir);
(<Control>formModel.find(["login"])).updateValue("new value"); (<Control>formModel.find(['login'])).updateValue('new value');
form.ngOnChanges({}); form.ngOnChanges({});
expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual("new value"); expect((<any>loginControlDir.valueAccessor).writtenValue).toEqual('new value');
}); });
it("should set up a sync validator", () => { it('should set up a sync validator', () => {
var formValidator = (c: any /** TODO #9100 */) => ({"custom": true}); var formValidator = (c: any /** TODO #9100 */) => ({'custom': true});
var f = new NgFormModel([formValidator], []); var f = new NgFormModel([formValidator], []);
f.form = formModel; f.form = formModel;
f.ngOnChanges({"form": new SimpleChange(null, null)}); f.ngOnChanges({'form': new SimpleChange(null, null)});
expect(formModel.errors).toEqual({"custom": true}); expect(formModel.errors).toEqual({'custom': true});
}); });
it("should set up an async validator", fakeAsync(() => { it('should set up an async validator', fakeAsync(() => {
var f = new NgFormModel([], [asyncValidator("expected")]); var f = new NgFormModel([], [asyncValidator('expected')]);
f.form = formModel; f.form = formModel;
f.ngOnChanges({"form": new SimpleChange(null, null)}); f.ngOnChanges({'form': new SimpleChange(null, null)});
tick(); tick();
expect(formModel.errors).toEqual({"async": true}); expect(formModel.errors).toEqual({'async': true});
})); }));
}); });
}); });
describe("NgForm", () => { describe('NgForm', () => {
var form: any /** TODO #9100 */; var form: any /** TODO #9100 */;
var formModel: ControlGroup; var formModel: ControlGroup;
var loginControlDir: any /** TODO #9100 */; var loginControlDir: any /** TODO #9100 */;
@ -299,14 +272,14 @@ export function main() {
formModel = form.form; formModel = form.form;
personControlGroupDir = new NgControlGroup(form, [], []); personControlGroupDir = new NgControlGroup(form, [], []);
personControlGroupDir.name = "person"; personControlGroupDir.name = 'person';
loginControlDir = new NgControlName(personControlGroupDir, null, null, [defaultAccessor]); loginControlDir = new NgControlName(personControlGroupDir, null, null, [defaultAccessor]);
loginControlDir.name = "login"; loginControlDir.name = 'login';
loginControlDir.valueAccessor = new DummyControlValueAccessor(); loginControlDir.valueAccessor = new DummyControlValueAccessor();
}); });
it("should reexport control properties", () => { it('should reexport control properties', () => {
expect(form.control).toBe(formModel); expect(form.control).toBe(formModel);
expect(form.value).toBe(formModel.value); expect(form.value).toBe(formModel.value);
expect(form.valid).toBe(formModel.valid); expect(form.valid).toBe(formModel.valid);
@ -317,21 +290,21 @@ export function main() {
expect(form.untouched).toBe(formModel.untouched); expect(form.untouched).toBe(formModel.untouched);
}); });
describe("addControl & addControlGroup", () => { describe('addControl & addControlGroup', () => {
it("should create a control with the given name", fakeAsync(() => { it('should create a control with the given name', fakeAsync(() => {
form.addControlGroup(personControlGroupDir); form.addControlGroup(personControlGroupDir);
form.addControl(loginControlDir); form.addControl(loginControlDir);
flushMicrotasks(); flushMicrotasks();
expect(formModel.find(["person", "login"])).not.toBeNull; expect(formModel.find(['person', 'login'])).not.toBeNull;
})); }));
// should update the form's value and validity // should update the form's value and validity
}); });
describe("removeControl & removeControlGroup", () => { describe('removeControl & removeControlGroup', () => {
it("should remove control", fakeAsync(() => { it('should remove control', fakeAsync(() => {
form.addControlGroup(personControlGroupDir); form.addControlGroup(personControlGroupDir);
form.addControl(loginControlDir); form.addControl(loginControlDir);
@ -340,45 +313,45 @@ export function main() {
flushMicrotasks(); flushMicrotasks();
expect(formModel.find(["person"])).toBeNull(); expect(formModel.find(['person'])).toBeNull();
expect(formModel.find(["person", "login"])).toBeNull(); expect(formModel.find(['person', 'login'])).toBeNull();
})); }));
// should update the form's value and validity // should update the form's value and validity
}); });
it("should set up sync validator", fakeAsync(() => { it('should set up sync validator', fakeAsync(() => {
var formValidator = (c: any /** TODO #9100 */) => ({"custom": true}); var formValidator = (c: any /** TODO #9100 */) => ({'custom': true});
var f = new NgForm([formValidator], []); var f = new NgForm([formValidator], []);
tick(); tick();
expect(f.form.errors).toEqual({"custom": true}); expect(f.form.errors).toEqual({'custom': true});
})); }));
it("should set up async validator", fakeAsync(() => { it('should set up async validator', fakeAsync(() => {
var f = new NgForm([], [asyncValidator("expected")]); var f = new NgForm([], [asyncValidator('expected')]);
tick(); tick();
expect(f.form.errors).toEqual({"async": true}); expect(f.form.errors).toEqual({'async': true});
})); }));
}); });
describe("NgControlGroup", () => { describe('NgControlGroup', () => {
var formModel: any /** TODO #9100 */; var formModel: any /** TODO #9100 */;
var controlGroupDir: any /** TODO #9100 */; var controlGroupDir: any /** TODO #9100 */;
beforeEach(() => { beforeEach(() => {
formModel = new ControlGroup({"login": new Control(null)}); formModel = new ControlGroup({'login': new Control(null)});
var parent = new NgFormModel([], []); var parent = new NgFormModel([], []);
parent.form = new ControlGroup({"group": formModel}); parent.form = new ControlGroup({'group': formModel});
controlGroupDir = new NgControlGroup(parent, [], []); controlGroupDir = new NgControlGroup(parent, [], []);
controlGroupDir.name = "group"; controlGroupDir.name = 'group';
}); });
it("should reexport control properties", () => { it('should reexport control properties', () => {
expect(controlGroupDir.control).toBe(formModel); expect(controlGroupDir.control).toBe(formModel);
expect(controlGroupDir.value).toBe(formModel.value); expect(controlGroupDir.value).toBe(formModel.value);
expect(controlGroupDir.valid).toBe(formModel.valid); expect(controlGroupDir.valid).toBe(formModel.valid);
@ -390,7 +363,7 @@ export function main() {
}); });
}); });
describe("NgFormControl", () => { describe('NgFormControl', () => {
var controlDir: any /** TODO #9100 */; var controlDir: any /** TODO #9100 */;
var control: any /** TODO #9100 */; var control: any /** TODO #9100 */;
var checkProperties = function(control: any /** TODO #9100 */) { var checkProperties = function(control: any /** TODO #9100 */) {
@ -412,36 +385,36 @@ export function main() {
controlDir.form = control; controlDir.form = control;
}); });
it("should reexport control properties", () => { checkProperties(control); }); it('should reexport control properties', () => { checkProperties(control); });
it("should reexport new control properties", () => { it('should reexport new control properties', () => {
var newControl = new Control(null); var newControl = new Control(null);
controlDir.form = newControl; controlDir.form = newControl;
controlDir.ngOnChanges({"form": new SimpleChange(control, newControl)}); controlDir.ngOnChanges({'form': new SimpleChange(control, newControl)});
checkProperties(newControl); checkProperties(newControl);
}); });
it("should set up validator", () => { it('should set up validator', () => {
expect(control.valid).toBe(true); expect(control.valid).toBe(true);
// this will add the required validator and recalculate the validity // this will add the required validator and recalculate the validity
controlDir.ngOnChanges({"form": new SimpleChange(null, control)}); controlDir.ngOnChanges({'form': new SimpleChange(null, control)});
expect(control.valid).toBe(false); expect(control.valid).toBe(false);
}); });
}); });
describe("NgModel", () => { describe('NgModel', () => {
var ngModel: any /** TODO #9100 */; var ngModel: any /** TODO #9100 */;
beforeEach(() => { beforeEach(() => {
ngModel = ngModel =
new NgModel([Validators.required], [asyncValidator("expected")], [defaultAccessor]); new NgModel([Validators.required], [asyncValidator('expected')], [defaultAccessor]);
ngModel.valueAccessor = new DummyControlValueAccessor(); ngModel.valueAccessor = new DummyControlValueAccessor();
}); });
it("should reexport control properties", () => { it('should reexport control properties', () => {
var control = ngModel.control; var control = ngModel.control;
expect(ngModel.control).toBe(control); expect(ngModel.control).toBe(control);
expect(ngModel.value).toBe(control.value); expect(ngModel.value).toBe(control.value);
@ -453,34 +426,34 @@ export function main() {
expect(ngModel.untouched).toBe(control.untouched); expect(ngModel.untouched).toBe(control.untouched);
}); });
it("should set up validator", fakeAsync(() => { it('should set up validator', fakeAsync(() => {
// this will add the required validator and recalculate the validity // this will add the required validator and recalculate the validity
ngModel.ngOnChanges({}); ngModel.ngOnChanges({});
tick(); tick();
expect(ngModel.control.errors).toEqual({"required": true}); expect(ngModel.control.errors).toEqual({'required': true});
ngModel.control.updateValue("someValue"); ngModel.control.updateValue('someValue');
tick(); tick();
expect(ngModel.control.errors).toEqual({"async": true}); expect(ngModel.control.errors).toEqual({'async': true});
})); }));
}); });
describe("NgControlName", () => { describe('NgControlName', () => {
var formModel: any /** TODO #9100 */; var formModel: any /** TODO #9100 */;
var controlNameDir: any /** TODO #9100 */; var controlNameDir: any /** TODO #9100 */;
beforeEach(() => { beforeEach(() => {
formModel = new Control("name"); formModel = new Control('name');
var parent = new NgFormModel([], []); var parent = new NgFormModel([], []);
parent.form = new ControlGroup({"name": formModel}); parent.form = new ControlGroup({'name': formModel});
controlNameDir = new NgControlName(parent, [], [], [defaultAccessor]); controlNameDir = new NgControlName(parent, [], [], [defaultAccessor]);
controlNameDir.name = "name"; controlNameDir.name = 'name';
}); });
it("should reexport control properties", () => { it('should reexport control properties', () => {
expect(controlNameDir.control).toBe(formModel); expect(controlNameDir.control).toBe(formModel);
expect(controlNameDir.value).toBe(formModel.value); expect(controlNameDir.value).toBe(formModel.value);
expect(controlNameDir.valid).toBe(formModel.valid); expect(controlNameDir.valid).toBe(formModel.valid);

View File

@ -1,67 +1,59 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/core/testing/testing_internal';
import {Control, FormBuilder} from '@angular/common'; import {Control, FormBuilder} from '@angular/common';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {PromiseWrapper} from '../../src/facade/promise'; import {PromiseWrapper} from '../../src/facade/promise';
export function main() { export function main() {
function syncValidator(_: any /** TODO #9100 */): any /** TODO #9100 */ { return null; } function syncValidator(_: any /** TODO #9100 */): any /** TODO #9100 */ { return null; }
function asyncValidator(_: any /** TODO #9100 */) { return PromiseWrapper.resolve(null); } function asyncValidator(_: any /** TODO #9100 */) { return PromiseWrapper.resolve(null); }
describe("Form Builder", () => { describe('Form Builder', () => {
var b: any /** TODO #9100 */; var b: any /** TODO #9100 */;
beforeEach(() => { b = new FormBuilder(); }); beforeEach(() => { b = new FormBuilder(); });
it("should create controls from a value", () => { it('should create controls from a value', () => {
var g = b.group({"login": "some value"}); var g = b.group({'login': 'some value'});
expect(g.controls["login"].value).toEqual("some value"); expect(g.controls['login'].value).toEqual('some value');
}); });
it("should create controls from an array", () => { it('should create controls from an array', () => {
var g = b.group( var g = b.group(
{"login": ["some value"], "password": ["some value", syncValidator, asyncValidator]}); {'login': ['some value'], 'password': ['some value', syncValidator, asyncValidator]});
expect(g.controls["login"].value).toEqual("some value"); expect(g.controls['login'].value).toEqual('some value');
expect(g.controls["password"].value).toEqual("some value"); expect(g.controls['password'].value).toEqual('some value');
expect(g.controls["password"].validator).toEqual(syncValidator); expect(g.controls['password'].validator).toEqual(syncValidator);
expect(g.controls["password"].asyncValidator).toEqual(asyncValidator); expect(g.controls['password'].asyncValidator).toEqual(asyncValidator);
}); });
it("should use controls", () => { it('should use controls', () => {
var g = b.group({"login": b.control("some value", syncValidator, asyncValidator)}); var g = b.group({'login': b.control('some value', syncValidator, asyncValidator)});
expect(g.controls["login"].value).toEqual("some value"); expect(g.controls['login'].value).toEqual('some value');
expect(g.controls["login"].validator).toBe(syncValidator); expect(g.controls['login'].validator).toBe(syncValidator);
expect(g.controls["login"].asyncValidator).toBe(asyncValidator); expect(g.controls['login'].asyncValidator).toBe(asyncValidator);
}); });
it("should create groups with optional controls", () => { it('should create groups with optional controls', () => {
var g = b.group({"login": "some value"}, {"optionals": {"login": false}}); var g = b.group({'login': 'some value'}, {'optionals': {'login': false}});
expect(g.contains("login")).toEqual(false); expect(g.contains('login')).toEqual(false);
}); });
it("should create groups with a custom validator", () => { it('should create groups with a custom validator', () => {
var g = b.group({"login": "some value"}, var g = b.group(
{"validator": syncValidator, "asyncValidator": asyncValidator}); {'login': 'some value'}, {'validator': syncValidator, 'asyncValidator': asyncValidator});
expect(g.validator).toBe(syncValidator); expect(g.validator).toBe(syncValidator);
expect(g.asyncValidator).toBe(asyncValidator); expect(g.asyncValidator).toBe(asyncValidator);
}); });
it("should create control arrays", () => { it('should create control arrays', () => {
var c = b.control("three"); var c = b.control('three');
var a = b.array(["one", ["two", syncValidator], c, b.array(['four'])], syncValidator, var a = b.array(
asyncValidator); ['one', ['two', syncValidator], c, b.array(['four'])], syncValidator, asyncValidator);
expect(a.value).toEqual(['one', 'two', 'three', ['four']]); expect(a.value).toEqual(['one', 'two', 'three', ['four']]);
expect(a.validator).toBe(syncValidator); expect(a.validator).toBe(syncValidator);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,9 @@
import { import {AbstractControl, Control, ControlArray, ControlGroup, Validators} from '@angular/common';
ddescribe, import {Log, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing';
describe, import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/core/testing/testing_internal';
import {fakeAsync, flushMicrotasks, Log, tick} from '@angular/core/testing';
import {ControlGroup, Control, Validators, AbstractControl, ControlArray} from '@angular/common';
import {PromiseWrapper} from '../../src/facade/promise';
import {EventEmitter, ObservableWrapper, TimerWrapper} from '../../src/facade/async'; import {EventEmitter, ObservableWrapper, TimerWrapper} from '../../src/facade/async';
import {PromiseWrapper} from '../../src/facade/promise';
export function main() { export function main() {
function validator(key: string, error: any) { function validator(key: string, error: any) {
@ -22,95 +14,98 @@ export function main() {
} }
} }
describe("Validators", () => { describe('Validators', () => {
describe("required", () => { describe('required', () => {
it("should error on an empty string", it('should error on an empty string',
() => { expect(Validators.required(new Control(""))).toEqual({"required": true}); }); () => { expect(Validators.required(new Control(''))).toEqual({'required': true}); });
it("should error on null", it('should error on null',
() => { expect(Validators.required(new Control(null))).toEqual({"required": true}); }); () => { expect(Validators.required(new Control(null))).toEqual({'required': true}); });
it("should not error on a non-empty string", it('should not error on a non-empty string',
() => { expect(Validators.required(new Control("not empty"))).toEqual(null); }); () => { expect(Validators.required(new Control('not empty'))).toEqual(null); });
it("should accept zero as valid", it('should accept zero as valid',
() => { expect(Validators.required(new Control(0))).toEqual(null); }); () => { expect(Validators.required(new Control(0))).toEqual(null); });
}); });
describe("minLength", () => { describe('minLength', () => {
it("should not error on an empty string", it('should not error on an empty string',
() => { expect(Validators.minLength(2)(new Control(""))).toEqual(null); }); () => { expect(Validators.minLength(2)(new Control(''))).toEqual(null); });
it("should not error on null", it('should not error on null',
() => { expect(Validators.minLength(2)(new Control(null))).toEqual(null); }); () => { expect(Validators.minLength(2)(new Control(null))).toEqual(null); });
it("should not error on valid strings", it('should not error on valid strings',
() => { expect(Validators.minLength(2)(new Control("aa"))).toEqual(null); }); () => { expect(Validators.minLength(2)(new Control('aa'))).toEqual(null); });
it("should error on short strings", () => { it('should error on short strings', () => {
expect(Validators.minLength(2)(new Control("a"))) expect(Validators.minLength(2)(new Control('a'))).toEqual({
.toEqual({"minlength": {"requiredLength": 2, "actualLength": 1}}); 'minlength': {'requiredLength': 2, 'actualLength': 1}
});
}); });
}); });
describe("maxLength", () => { describe('maxLength', () => {
it("should not error on an empty string", it('should not error on an empty string',
() => { expect(Validators.maxLength(2)(new Control(""))).toEqual(null); }); () => { expect(Validators.maxLength(2)(new Control(''))).toEqual(null); });
it("should not error on null", it('should not error on null',
() => { expect(Validators.maxLength(2)(new Control(null))).toEqual(null); }); () => { expect(Validators.maxLength(2)(new Control(null))).toEqual(null); });
it("should not error on valid strings", it('should not error on valid strings',
() => { expect(Validators.maxLength(2)(new Control("aa"))).toEqual(null); }); () => { expect(Validators.maxLength(2)(new Control('aa'))).toEqual(null); });
it("should error on long strings", () => { it('should error on long strings', () => {
expect(Validators.maxLength(2)(new Control("aaa"))) expect(Validators.maxLength(2)(new Control('aaa'))).toEqual({
.toEqual({"maxlength": {"requiredLength": 2, "actualLength": 3}}); 'maxlength': {'requiredLength': 2, 'actualLength': 3}
});
}); });
}); });
describe("pattern", () => { describe('pattern', () => {
it("should not error on an empty string", it('should not error on an empty string',
() => { expect(Validators.pattern("[a-zA-Z ]*")(new Control(""))).toEqual(null); }); () => { expect(Validators.pattern('[a-zA-Z ]*')(new Control(''))).toEqual(null); });
it("should not error on null", it('should not error on null',
() => { expect(Validators.pattern("[a-zA-Z ]*")(new Control(null))).toEqual(null); }); () => { expect(Validators.pattern('[a-zA-Z ]*')(new Control(null))).toEqual(null); });
it("should not error on valid strings", it('should not error on valid strings',
() => { expect(Validators.pattern("[a-zA-Z ]*")(new Control("aaAA"))).toEqual(null); }); () => { expect(Validators.pattern('[a-zA-Z ]*')(new Control('aaAA'))).toEqual(null); });
it("should error on failure to match string", () => { it('should error on failure to match string', () => {
expect(Validators.pattern("[a-zA-Z ]*")(new Control("aaa0"))) expect(Validators.pattern('[a-zA-Z ]*')(new Control('aaa0'))).toEqual({
.toEqual({"pattern": {"requiredPattern": "^[a-zA-Z ]*$", "actualValue": "aaa0"}}); 'pattern': {'requiredPattern': '^[a-zA-Z ]*$', 'actualValue': 'aaa0'}
});
}); });
}); });
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', () => {
var c = Validators.compose([validator("a", true), validator("b", true)]); var c = Validators.compose([validator('a', true), validator('b', true)]);
expect(c(new Control(""))).toEqual({"a": true, "b": true}); expect(c(new Control(''))).toEqual({'a': true, 'b': true});
}); });
it("should run validators left to right", () => { it('should run validators left to right', () => {
var c = Validators.compose([validator("a", 1), validator("a", 2)]); var c = Validators.compose([validator('a', 1), validator('a', 2)]);
expect(c(new Control(""))).toEqual({"a": 2}); expect(c(new Control(''))).toEqual({'a': 2});
}); });
it("should return null when no errors", () => { it('should return null when no errors', () => {
var c = Validators.compose([Validators.nullValidator, Validators.nullValidator]); var c = Validators.compose([Validators.nullValidator, Validators.nullValidator]);
expect(c(new Control(""))).toEqual(null); expect(c(new Control(''))).toEqual(null);
}); });
it("should ignore nulls", () => { it('should ignore nulls', () => {
var c = Validators.compose([null, Validators.required]); var c = Validators.compose([null, Validators.required]);
expect(c(new Control(""))).toEqual({"required": true}); expect(c(new Control(''))).toEqual({'required': true});
}); });
}); });
describe("composeAsync", () => { describe('composeAsync', () => {
function asyncValidator(expected: any /** TODO #9100 */, response: any /** TODO #9100 */) { function asyncValidator(expected: any /** TODO #9100 */, response: any /** TODO #9100 */) {
return (c: any /** TODO #9100 */) => { return (c: any /** TODO #9100 */) => {
var emitter = new EventEmitter(); var emitter = new EventEmitter();
@ -127,43 +122,42 @@ export function main() {
}; };
} }
it("should return null when given null", it('should return null when given null',
() => { expect(Validators.composeAsync(null)).toEqual(null); }); () => { expect(Validators.composeAsync(null)).toEqual(null); });
it("should collect errors from all the validators", fakeAsync(() => { it('should collect errors from all the validators', fakeAsync(() => {
var c = Validators.composeAsync([ var c = Validators.composeAsync([
asyncValidator("expected", {"one": true}), asyncValidator('expected', {'one': true}), asyncValidator('expected', {'two': true})
asyncValidator("expected", {"two": true})
]); ]);
var value: any /** TODO #9100 */ = null; var value: any /** TODO #9100 */ = null;
(<Promise<any>>c(new Control("invalid"))).then(v => value = v); (<Promise<any>>c(new Control('invalid'))).then(v => value = v);
tick(1); tick(1);
expect(value).toEqual({"one": true, "two": true}); expect(value).toEqual({'one': true, 'two': true});
})); }));
it("should return null when no errors", fakeAsync(() => { it('should return null when no errors', fakeAsync(() => {
var c = Validators.composeAsync([asyncValidator("expected", {"one": true})]); var c = Validators.composeAsync([asyncValidator('expected', {'one': true})]);
var value: any /** TODO #9100 */ = null; var value: any /** TODO #9100 */ = null;
(<Promise<any>>c(new Control("expected"))).then(v => value = v); (<Promise<any>>c(new Control('expected'))).then(v => value = v);
tick(1); tick(1);
expect(value).toEqual(null); expect(value).toEqual(null);
})); }));
it("should ignore nulls", fakeAsync(() => { it('should ignore nulls', fakeAsync(() => {
var c = Validators.composeAsync([asyncValidator("expected", {"one": true}), null]); var c = Validators.composeAsync([asyncValidator('expected', {'one': true}), null]);
var value: any /** TODO #9100 */ = null; var value: any /** TODO #9100 */ = null;
(<Promise<any>>c(new Control("invalid"))).then(v => value = v); (<Promise<any>>c(new Control('invalid'))).then(v => value = v);
tick(1); tick(1);
expect(value).toEqual({"one": true}); expect(value).toEqual({'one': true});
})); }));
}); });
}); });

View File

@ -1,31 +1,16 @@
import { import {ddescribe, describe, it, iit, xit, expect, beforeEach, afterEach, inject,} from '@angular/core/testing/testing_internal';
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
inject,
} from '@angular/core/testing/testing_internal';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {SpyChangeDetectorRef} from '../spies'; import {SpyChangeDetectorRef} from '../spies';
import {isBlank} from '../../src/facade/lang'; import {isBlank} from '../../src/facade/lang';
import {AsyncPipe} from '@angular/common'; import {AsyncPipe} from '@angular/common';
import {WrappedValue} from '@angular/core'; import {WrappedValue} from '@angular/core';
import { import {EventEmitter, ObservableWrapper, PromiseWrapper, TimerWrapper} from '../../src/facade/async';
EventEmitter,
ObservableWrapper,
PromiseWrapper,
TimerWrapper
} from '../../src/facade/async';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {PromiseCompleter} from '../../src/facade/promise'; import {PromiseCompleter} from '../../src/facade/promise';
import {browserDetection} from '@angular/platform-browser/testing'; import {browserDetection} from '@angular/platform-browser/testing';
export function main() { export function main() {
describe("AsyncPipe", () => { describe('AsyncPipe', () => {
describe('Observable', () => { describe('Observable', () => {
var emitter: any /** TODO #9100 */; var emitter: any /** TODO #9100 */;
@ -39,11 +24,11 @@ export function main() {
pipe = new AsyncPipe(ref); pipe = new AsyncPipe(ref);
}); });
describe("transform", () => { describe('transform', () => {
it("should return null when subscribing to an observable", it('should return null when subscribing to an observable',
() => { expect(pipe.transform(emitter)).toBe(null); }); () => { expect(pipe.transform(emitter)).toBe(null); });
it("should return the latest available value wrapped", it('should return the latest available value wrapped',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
pipe.transform(emitter); pipe.transform(emitter);
@ -56,7 +41,7 @@ export function main() {
})); }));
it("should return same value when nothing has changed since the last call", it('should return same value when nothing has changed since the last call',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
pipe.transform(emitter); pipe.transform(emitter);
ObservableWrapper.callEmit(emitter, message); ObservableWrapper.callEmit(emitter, message);
@ -68,7 +53,7 @@ export function main() {
}, 0) }, 0)
})); }));
it("should dispose of the existing subscription when subscribing to a new observable", it('should dispose of the existing subscription when subscribing to a new observable',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
pipe.transform(emitter); pipe.transform(emitter);
@ -84,7 +69,7 @@ export function main() {
}, 0) }, 0)
})); }));
it("should request a change detection check upon receiving a new value", it('should request a change detection check upon receiving a new value',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
pipe.transform(emitter); pipe.transform(emitter);
ObservableWrapper.callEmit(emitter, message); ObservableWrapper.callEmit(emitter, message);
@ -96,11 +81,12 @@ export function main() {
})); }));
}); });
describe("ngOnDestroy", () => { describe('ngOnDestroy', () => {
it("should do nothing when no subscription", it('should do nothing when no subscription',
() => { expect(() => pipe.ngOnDestroy()).not.toThrow(); }); () => { expect(() => pipe.ngOnDestroy()).not.toThrow(); });
it("should dispose of the existing subscription", inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { it('should dispose of the existing subscription',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
pipe.transform(emitter); pipe.transform(emitter);
pipe.ngOnDestroy(); pipe.ngOnDestroy();
@ -114,7 +100,7 @@ export function main() {
}); });
}); });
describe("Promise", () => { describe('Promise', () => {
var message = new Object(); var message = new Object();
var pipe: AsyncPipe; var pipe: AsyncPipe;
var completer: PromiseCompleter<any>; var completer: PromiseCompleter<any>;
@ -128,11 +114,12 @@ export function main() {
pipe = new AsyncPipe(<any>ref); pipe = new AsyncPipe(<any>ref);
}); });
describe("transform", () => { describe('transform', () => {
it("should return null when subscribing to a promise", it('should return null when subscribing to a promise',
() => { expect(pipe.transform(completer.promise)).toBe(null); }); () => { expect(pipe.transform(completer.promise)).toBe(null); });
it("should return the latest available value", inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { it('should return the latest available value',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
pipe.transform(completer.promise); pipe.transform(completer.promise);
completer.resolve(message); completer.resolve(message);
@ -143,7 +130,7 @@ export function main() {
}, timer) }, timer)
})); }));
it("should return unwrapped value when nothing has changed since the last call", it('should return unwrapped value when nothing has changed since the last call',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
pipe.transform(completer.promise); pipe.transform(completer.promise);
completer.resolve(message); completer.resolve(message);
@ -155,7 +142,7 @@ export function main() {
}, timer) }, timer)
})); }));
it("should dispose of the existing subscription when subscribing to a new promise", it('should dispose of the existing subscription when subscribing to a new promise',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
pipe.transform(completer.promise); pipe.transform(completer.promise);
@ -171,7 +158,7 @@ export function main() {
}, timer) }, timer)
})); }));
it("should request a change detection check upon receiving a new value", it('should request a change detection check upon receiving a new value',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
var markForCheck = ref.spy('markForCheck'); var markForCheck = ref.spy('markForCheck');
pipe.transform(completer.promise); pipe.transform(completer.promise);
@ -183,22 +170,23 @@ export function main() {
}, timer) }, timer)
})); }));
describe("ngOnDestroy", () => { describe('ngOnDestroy', () => {
it("should do nothing when no source", it('should do nothing when no source',
() => { expect(() => pipe.ngOnDestroy()).not.toThrow(); }); () => { expect(() => pipe.ngOnDestroy()).not.toThrow(); });
it("should dispose of the existing source", inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { it('should dispose of the existing source',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
pipe.transform(completer.promise); pipe.transform(completer.promise);
expect(pipe.transform(completer.promise)).toBe(null); expect(pipe.transform(completer.promise)).toBe(null);
completer.resolve(message) completer.resolve(message)
TimerWrapper.setTimeout(() => { TimerWrapper.setTimeout(() => {
expect(pipe.transform(completer.promise)).toEqual(new WrappedValue(message)); expect(pipe.transform(completer.promise)).toEqual(new WrappedValue(message));
pipe.ngOnDestroy(); pipe.ngOnDestroy();
expect(pipe.transform(completer.promise)).toBe(null); expect(pipe.transform(completer.promise)).toBe(null);
async.done(); async.done();
}, timer); }, timer);
})); }));
}); });
}); });
@ -214,7 +202,7 @@ export function main() {
describe('other types', () => { describe('other types', () => {
it('should throw when given an invalid object', () => { it('should throw when given an invalid object', () => {
var pipe = new AsyncPipe(null); var pipe = new AsyncPipe(null);
expect(() => pipe.transform(<any>"some bogus object")).toThrowError(); expect(() => pipe.transform(<any>'some bogus object')).toThrowError();
}); });
}); });
}); });

View File

@ -1,21 +1,12 @@
import { import {DatePipe} from '@angular/common';
ddescribe, import {PipeResolver} from '@angular/compiler/src/pipe_resolver';
describe, import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/core/testing/testing_internal';
import {browserDetection} from '@angular/platform-browser/testing'; import {browserDetection} from '@angular/platform-browser/testing';
import {DatePipe} from '@angular/common';
import {DateWrapper} from '../../src/facade/lang'; import {DateWrapper} from '../../src/facade/lang';
import {PipeResolver} from '@angular/compiler/src/pipe_resolver';
export function main() { export function main() {
describe("DatePipe", () => { describe('DatePipe', () => {
var date: any /** TODO #9100 */; var date: any /** TODO #9100 */;
var pipe: any /** TODO #9100 */; var pipe: any /** TODO #9100 */;
@ -27,23 +18,23 @@ export function main() {
it('should be marked as pure', it('should be marked as pure',
() => { expect(new PipeResolver().resolve(DatePipe).pure).toEqual(true); }); () => { expect(new PipeResolver().resolve(DatePipe).pure).toEqual(true); });
describe("supports", () => { describe('supports', () => {
it("should support date", () => { expect(pipe.supports(date)).toBe(true); }); it('should support date', () => { expect(pipe.supports(date)).toBe(true); });
it("should support int", () => { expect(pipe.supports(123456789)).toBe(true); }); it('should support int', () => { expect(pipe.supports(123456789)).toBe(true); });
it("should support ISO string", it('should support ISO string',
() => { expect(pipe.supports("2015-06-15T21:43:11Z")).toBe(true); }); () => { expect(pipe.supports('2015-06-15T21:43:11Z')).toBe(true); });
it("should not support other objects", () => { it('should not support other objects', () => {
expect(pipe.supports(new Object())).toBe(false); expect(pipe.supports(new Object())).toBe(false);
expect(pipe.supports(null)).toBe(false); expect(pipe.supports(null)).toBe(false);
expect(pipe.supports("")).toBe(false); expect(pipe.supports('')).toBe(false);
}); });
}); });
// TODO(mlaval): enable tests when Intl API is no longer used, see // TODO(mlaval): enable tests when Intl API is no longer used, see
// https://github.com/angular/angular/issues/3333 // https://github.com/angular/angular/issues/3333
if (browserDetection.supportsIntlApi) { if (browserDetection.supportsIntlApi) {
describe("transform", () => { describe('transform', () => {
it('should format each component correctly', () => { it('should format each component correctly', () => {
expect(pipe.transform(date, 'y')).toEqual('2015'); expect(pipe.transform(date, 'y')).toEqual('2015');
expect(pipe.transform(date, 'yy')).toEqual('15'); expect(pipe.transform(date, 'yy')).toEqual('15');

View File

@ -1,57 +1,50 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/core/testing/testing_internal';
import {I18nPluralPipe} from '@angular/common'; import {I18nPluralPipe} from '@angular/common';
import {PipeResolver} from '@angular/compiler/src/pipe_resolver'; import {PipeResolver} from '@angular/compiler/src/pipe_resolver';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
export function main() { export function main() {
describe("I18nPluralPipe", () => { describe('I18nPluralPipe', () => {
var pipe: any /** TODO #9100 */; var pipe: any /** TODO #9100 */;
var mapping = {'=0': 'No messages.', '=1': 'One message.', 'other': 'There are some messages.'}; var mapping = {'=0': 'No messages.', '=1': 'One message.', 'other': 'There are some messages.'};
var interpolatedMapping = var interpolatedMapping = {
{'=0': 'No messages.', '=1': 'One message.', 'other': 'There are # messages, that is #.'}; '=0': 'No messages.',
'=1': 'One message.',
'other': 'There are # messages, that is #.'
};
beforeEach(() => { pipe = new I18nPluralPipe(); }); beforeEach(() => { pipe = new I18nPluralPipe(); });
it('should be marked as pure', it('should be marked as pure',
() => { expect(new PipeResolver().resolve(I18nPluralPipe).pure).toEqual(true); }); () => { expect(new PipeResolver().resolve(I18nPluralPipe).pure).toEqual(true); });
describe("transform", () => { describe('transform', () => {
it("should return 0 text if value is 0", () => { it('should return 0 text if value is 0', () => {
var val = pipe.transform(0, mapping); var val = pipe.transform(0, mapping);
expect(val).toEqual('No messages.'); expect(val).toEqual('No messages.');
}); });
it("should return 1 text if value is 1", () => { it('should return 1 text if value is 1', () => {
var val = pipe.transform(1, mapping); var val = pipe.transform(1, mapping);
expect(val).toEqual('One message.'); expect(val).toEqual('One message.');
}); });
it("should return other text if value is anything other than 0 or 1", () => { it('should return other text if value is anything other than 0 or 1', () => {
var val = pipe.transform(6, mapping); var val = pipe.transform(6, mapping);
expect(val).toEqual('There are some messages.'); expect(val).toEqual('There are some messages.');
}); });
it("should interpolate the value into the text where indicated", () => { it('should interpolate the value into the text where indicated', () => {
var val = pipe.transform(6, interpolatedMapping); var val = pipe.transform(6, interpolatedMapping);
expect(val).toEqual('There are 6 messages, that is 6.'); expect(val).toEqual('There are 6 messages, that is 6.');
}); });
it("should use 'other' if value is undefined", () => { it('should use \'other\' if value is undefined', () => {
var messageLength: any /** TODO #9100 */; var messageLength: any /** TODO #9100 */;
var val = pipe.transform(messageLength, interpolatedMapping); var val = pipe.transform(messageLength, interpolatedMapping);
expect(val).toEqual('There are messages, that is .'); expect(val).toEqual('There are messages, that is .');
}); });
it("should not support bad arguments", it('should not support bad arguments',
() => { expect(() => pipe.transform(0, 'hey')).toThrowError(); }); () => { expect(() => pipe.transform(0, 'hey')).toThrowError(); });
}); });

Some files were not shown because too many files have changed in this diff Show More