feat(forms): migrated forms to typescript
This commit is contained in:
parent
fed86fc8ac
commit
00c3693daa
@ -2,11 +2,14 @@
|
|||||||
* @module
|
* @module
|
||||||
* @public
|
* @public
|
||||||
* @description
|
* @description
|
||||||
* This module is used for handling user input, by defining and building a {@link ControlGroup} that consists of
|
* This module is used for handling user input, by defining and building a {@link ControlGroup} that
|
||||||
* {@link Control} objects, and mapping them onto the DOM. {@link Control} objects can then be used to read information
|
* consists of
|
||||||
|
* {@link Control} objects, and mapping them onto the DOM. {@link Control} objects can then be used
|
||||||
|
* to read information
|
||||||
* from the form DOM elements.
|
* from the form DOM elements.
|
||||||
*
|
*
|
||||||
* This module is not included in the `angular2` module; you must import the forms module explicitly.
|
* This module is not included in the `angular2` module; you must import the forms module
|
||||||
|
* explicitly.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
@ -1,3 +1,6 @@
|
|||||||
library angular2.core.decorators;
|
library angular2.core.decorators;
|
||||||
|
|
||||||
|
export '../annotations_impl/annotations.dart';
|
||||||
|
export '../annotations_impl/visibility.dart';
|
||||||
|
|
||||||
/* This file is empty because, Dart does not have decorators. */
|
/* This file is empty because, Dart does not have decorators. */
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import {ComponentAnnotation, DirectiveAnnotation} from './annotations';
|
import {ComponentAnnotation, DirectiveAnnotation} from './annotations';
|
||||||
import {ViewAnnotation} from './view';
|
import {ViewAnnotation} from './view';
|
||||||
import {AncestorAnnotation, ParentAnnotation} from './visibility';
|
import {
|
||||||
|
SelfAnnotation,
|
||||||
|
ParentAnnotation,
|
||||||
|
AncestorAnnotation,
|
||||||
|
UnboundedAnnotation
|
||||||
|
} from './visibility';
|
||||||
import {AttributeAnnotation, QueryAnnotation} from './di';
|
import {AttributeAnnotation, QueryAnnotation} from './di';
|
||||||
import {makeDecorator, makeParamDecorator} from '../../util/decorators';
|
import {makeDecorator, makeParamDecorator} from '../../util/decorators';
|
||||||
|
|
||||||
@ -12,8 +17,10 @@ export var Directive = makeDecorator(DirectiveAnnotation);
|
|||||||
export var View = makeDecorator(ViewAnnotation);
|
export var View = makeDecorator(ViewAnnotation);
|
||||||
|
|
||||||
/* from visibility */
|
/* from visibility */
|
||||||
export var Ancestor = makeParamDecorator(AncestorAnnotation);
|
export var Self = makeParamDecorator(SelfAnnotation);
|
||||||
export var Parent = makeParamDecorator(ParentAnnotation);
|
export var Parent = makeParamDecorator(ParentAnnotation);
|
||||||
|
export var Ancestor = makeParamDecorator(AncestorAnnotation);
|
||||||
|
export var Unbounded = makeParamDecorator(UnboundedAnnotation);
|
||||||
|
|
||||||
/* from di */
|
/* from di */
|
||||||
export var Attribute = makeParamDecorator(AttributeAnnotation);
|
export var Attribute = makeParamDecorator(AttributeAnnotation);
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export {
|
export {
|
||||||
|
Self as SelfAnnotation,
|
||||||
Ancestor as AncestorAnnotation,
|
Ancestor as AncestorAnnotation,
|
||||||
Parent as ParentAnnotation,
|
Parent as ParentAnnotation,
|
||||||
|
Unbounded as UnboundedAnnotation
|
||||||
} from '../annotations_impl/visibility';
|
} from '../annotations_impl/visibility';
|
||||||
|
@ -10,7 +10,6 @@ export class DirectiveResolver {
|
|||||||
if (isPresent(annotations)) {
|
if (isPresent(annotations)) {
|
||||||
for (var i = 0; i < annotations.length; i++) {
|
for (var i = 0; i < annotations.length; i++) {
|
||||||
var annotation = annotations[i];
|
var annotation = annotations[i];
|
||||||
|
|
||||||
if (annotation instanceof Directive) {
|
if (annotation instanceof Directive) {
|
||||||
return annotation;
|
return annotation;
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import {Directive} from 'angular2/src/core/annotations_impl/annotations';
|
import {Directive, Ancestor} from 'angular2/src/core/annotations/decorators';
|
||||||
import {Ancestor} from 'angular2/src/core/annotations_impl/visibility';
|
import {Optional} from 'angular2/src/di/decorators';
|
||||||
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
||||||
import {Optional} from 'angular2/src/di/annotations_impl';
|
|
||||||
import {Renderer} from 'angular2/src/render/api';
|
import {Renderer} from 'angular2/src/render/api';
|
||||||
import {isPresent, isString, CONST_EXPR, isBlank, BaseException} from 'angular2/src/facade/lang';
|
import {
|
||||||
|
isPresent,
|
||||||
|
isString,
|
||||||
|
CONST_EXPR,
|
||||||
|
isBlank,
|
||||||
|
BaseException,
|
||||||
|
Type
|
||||||
|
} from 'angular2/src/facade/lang';
|
||||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {ControlGroup, Control, isControl} from './model';
|
import {ControlGroup, Control, isControl} from './model';
|
||||||
import {Validators} from './validators';
|
import {Validators} from './validators';
|
||||||
|
|
||||||
//export interface ControlValueAccessor {
|
function _lookupControl(groupDirective: ControlGroupDirective, controlOrName: any): any {
|
||||||
// writeValue(value):void{}
|
|
||||||
// set onChange(fn){}
|
|
||||||
//}
|
|
||||||
|
|
||||||
function _lookupControl(groupDirective:ControlGroupDirective, controlOrName:any):any {
|
|
||||||
if (isControl(controlOrName)) {
|
if (isControl(controlOrName)) {
|
||||||
return controlOrName;
|
return controlOrName;
|
||||||
}
|
}
|
||||||
@ -31,8 +32,10 @@ function _lookupControl(groupDirective:ControlGroupDirective, controlOrName:any)
|
|||||||
return control;
|
return control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default accessor for writing a value and listening to changes that is used by a {@link Control} directive.
|
* The default accessor for writing a value and listening to changes that is used by a {@link
|
||||||
|
* Control} directive.
|
||||||
*
|
*
|
||||||
* This is the default strategy that Angular uses when no other accessor is applied.
|
* This is the default strategy that Angular uses when no other accessor is applied.
|
||||||
*
|
*
|
||||||
@ -45,143 +48,17 @@ function _lookupControl(groupDirective:ControlGroupDirective, controlOrName:any)
|
|||||||
*/
|
*/
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[control]',
|
selector: '[control]',
|
||||||
hostListeners: {
|
hostListeners:
|
||||||
'change' : 'onChange($event.target.value)',
|
{'change': 'onChange($event.target.value)', 'input': 'onChange($event.target.value)'},
|
||||||
'input' : 'onChange($event.target.value)'
|
hostProperties: {'value': 'value'}
|
||||||
},
|
|
||||||
hostProperties: {
|
|
||||||
'value' : 'value'
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
export class DefaultValueAccessor {
|
export class DefaultValueAccessor {
|
||||||
value;
|
value;
|
||||||
onChange:Function;
|
onChange: Function;
|
||||||
|
|
||||||
constructor() {
|
constructor() { this.onChange = (_) => {}; }
|
||||||
this.onChange = (_) => {};
|
|
||||||
}
|
|
||||||
|
|
||||||
writeValue(value) {
|
writeValue(value) { this.value = value }
|
||||||
this.value = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The accessor for writing a value and listening to changes on a checkbox input element.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* # Example
|
|
||||||
* ```
|
|
||||||
* <input type="checkbox" [control]="rememberLogin">
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @exportedAs angular2/forms
|
|
||||||
*/
|
|
||||||
@Directive({
|
|
||||||
selector: 'input[type=checkbox][control]',
|
|
||||||
hostListeners: {
|
|
||||||
'change' : 'onChange($event.target.checked)'
|
|
||||||
},
|
|
||||||
hostProperties: {
|
|
||||||
'checked' : 'checked'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export class CheckboxControlValueAccessor {
|
|
||||||
_elementRef:ElementRef;
|
|
||||||
_renderer:Renderer;
|
|
||||||
|
|
||||||
checked:boolean;
|
|
||||||
onChange:Function;
|
|
||||||
|
|
||||||
constructor(cd:ControlDirective, elementRef:ElementRef, renderer:Renderer) {
|
|
||||||
this.onChange = (_) => {};
|
|
||||||
this._elementRef = elementRef;
|
|
||||||
this._renderer = renderer;
|
|
||||||
cd.valueAccessor = this; //ControlDirective should inject CheckboxControlDirective
|
|
||||||
}
|
|
||||||
|
|
||||||
writeValue(value) {
|
|
||||||
this._renderer.setElementProperty(this._elementRef.parentView.render, this._elementRef.boundElementIndex,
|
|
||||||
'checked', value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds a control to a DOM element.
|
|
||||||
*
|
|
||||||
* # Example
|
|
||||||
*
|
|
||||||
* In this example, we bind the control to an input element. When the value of the input element changes, the value of
|
|
||||||
* the control will reflect that change. Likewise, if the value of the control changes, the input element reflects that
|
|
||||||
* change.
|
|
||||||
*
|
|
||||||
* Here we use {@link formDirectives}, rather than importing each form directive individually, e.g.
|
|
||||||
* `ControlDirective`, `ControlGroupDirective`. This is just a shorthand for the same end result.
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* @Component({selector: "login-comp"})
|
|
||||||
* @View({
|
|
||||||
* directives: [formDirectives],
|
|
||||||
* inline: "<input type='text' [control]='loginControl'>"
|
|
||||||
* })
|
|
||||||
* class LoginComp {
|
|
||||||
* loginControl:Control;
|
|
||||||
*
|
|
||||||
* constructor() {
|
|
||||||
* this.loginControl = new Control('');
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @exportedAs angular2/forms
|
|
||||||
*/
|
|
||||||
@Directive({
|
|
||||||
selector: '[control]',
|
|
||||||
properties: {
|
|
||||||
'controlOrName' : 'control'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export class ControlDirective {
|
|
||||||
_groupDirective:ControlGroupDirective;
|
|
||||||
|
|
||||||
_controlOrName:any;
|
|
||||||
valueAccessor:any; //ControlValueAccessor
|
|
||||||
|
|
||||||
validator:Function;
|
|
||||||
|
|
||||||
constructor(@Optional() @Ancestor() groupDirective:ControlGroupDirective, valueAccessor:DefaultValueAccessor) {
|
|
||||||
this._groupDirective = groupDirective;
|
|
||||||
this._controlOrName = null;
|
|
||||||
this.valueAccessor = valueAccessor;
|
|
||||||
this.validator = Validators.nullValidator;
|
|
||||||
}
|
|
||||||
|
|
||||||
set controlOrName(controlOrName) {
|
|
||||||
this._controlOrName = controlOrName;
|
|
||||||
|
|
||||||
if(isPresent(this._groupDirective)) {
|
|
||||||
this._groupDirective.addDirective(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
var c = this._control();
|
|
||||||
c.validator = Validators.compose([c.validator, this.validator]);
|
|
||||||
|
|
||||||
this._updateDomValue();
|
|
||||||
this._setUpUpdateControlValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateDomValue() {
|
|
||||||
this.valueAccessor.writeValue(this._control().value);
|
|
||||||
}
|
|
||||||
|
|
||||||
_setUpUpdateControlValue() {
|
|
||||||
this.valueAccessor.onChange = (newValue) => this._control().updateValue(newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
_control() {
|
|
||||||
return _lookupControl(this._groupDirective, this._controlOrName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -189,7 +66,8 @@ export class ControlDirective {
|
|||||||
*
|
*
|
||||||
* # Example
|
* # Example
|
||||||
*
|
*
|
||||||
* In this example, we bind the control group to the form element, and we bind the login and password controls to the
|
* In this example, we bind the control group to the form element, and we bind the login and
|
||||||
|
* password controls to the
|
||||||
* login and password elements.
|
* login and password elements.
|
||||||
*
|
*
|
||||||
* Here we use {@link formDirectives}, rather than importing each form directive individually, e.g.
|
* Here we use {@link formDirectives}, rather than importing each form directive individually, e.g.
|
||||||
@ -224,18 +102,13 @@ export class ControlDirective {
|
|||||||
*
|
*
|
||||||
* @exportedAs angular2/forms
|
* @exportedAs angular2/forms
|
||||||
*/
|
*/
|
||||||
@Directive({
|
@Directive({selector: '[control-group]', properties: {'controlOrName': 'control-group'}})
|
||||||
selector: '[control-group]',
|
|
||||||
properties: {
|
|
||||||
'controlOrName' : 'control-group'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export class ControlGroupDirective {
|
export class ControlGroupDirective {
|
||||||
_groupDirective:ControlGroupDirective;
|
_groupDirective: ControlGroupDirective;
|
||||||
_directives:List<ControlDirective>;
|
_directives: List<ControlDirective>;
|
||||||
_controlOrName:any;
|
_controlOrName: any;
|
||||||
|
|
||||||
constructor(@Optional() @Ancestor() groupDirective:ControlGroupDirective) {
|
constructor(@Optional() @Ancestor() groupDirective: ControlGroupDirective) {
|
||||||
this._groupDirective = groupDirective;
|
this._groupDirective = groupDirective;
|
||||||
this._directives = ListWrapper.create();
|
this._directives = ListWrapper.create();
|
||||||
}
|
}
|
||||||
@ -245,23 +118,126 @@ export class ControlGroupDirective {
|
|||||||
this._updateDomValue();
|
this._updateDomValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateDomValue() {
|
_updateDomValue() { ListWrapper.forEach(this._directives, (cd) => cd._updateDomValue()); }
|
||||||
ListWrapper.forEach(this._directives, (cd) => cd._updateDomValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
addDirective(c:ControlDirective) {
|
addDirective(c: ControlDirective) { ListWrapper.push(this._directives, c); }
|
||||||
ListWrapper.push(this._directives, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
findControl(name:string):any {
|
findControl(name: string): any { return this._getControlGroup().controls[name]; }
|
||||||
return this._getControlGroup().controls[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
_getControlGroup():ControlGroup {
|
_getControlGroup(): ControlGroup {
|
||||||
return _lookupControl(this._groupDirective, this._controlOrName);
|
return _lookupControl(this._groupDirective, this._controlOrName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds a control to a DOM element.
|
||||||
|
*
|
||||||
|
* # Example
|
||||||
|
*
|
||||||
|
* In this example, we bind the control to an input element. When the value of the input element
|
||||||
|
* changes, the value of
|
||||||
|
* the control will reflect that change. Likewise, if the value of the control changes, the input
|
||||||
|
* element reflects that
|
||||||
|
* change.
|
||||||
|
*
|
||||||
|
* Here we use {@link formDirectives}, rather than importing each form directive individually, e.g.
|
||||||
|
* `ControlDirective`, `ControlGroupDirective`. This is just a shorthand for the same end result.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* @Component({selector: "login-comp"})
|
||||||
|
* @View({
|
||||||
|
* directives: [formDirectives],
|
||||||
|
* inline: "<input type='text' [control]='loginControl'>"
|
||||||
|
* })
|
||||||
|
* class LoginComp {
|
||||||
|
* loginControl:Control;
|
||||||
|
*
|
||||||
|
* constructor() {
|
||||||
|
* this.loginControl = new Control('');
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @exportedAs angular2/forms
|
||||||
|
*/
|
||||||
|
@Directive({selector: '[control]', properties: {'controlOrName': 'control'}})
|
||||||
|
export class ControlDirective {
|
||||||
|
_groupDirective: ControlGroupDirective;
|
||||||
|
|
||||||
|
_controlOrName: any;
|
||||||
|
valueAccessor: any; // ControlValueAccessor
|
||||||
|
|
||||||
|
validator: Function;
|
||||||
|
|
||||||
|
constructor(@Optional() @Ancestor() groupDirective: ControlGroupDirective,
|
||||||
|
valueAccessor: DefaultValueAccessor) {
|
||||||
|
this._groupDirective = groupDirective;
|
||||||
|
this._controlOrName = null;
|
||||||
|
this.valueAccessor = valueAccessor;
|
||||||
|
this.validator = Validators.nullValidator;
|
||||||
|
}
|
||||||
|
|
||||||
|
set controlOrName(controlOrName) {
|
||||||
|
this._controlOrName = controlOrName;
|
||||||
|
|
||||||
|
if (isPresent(this._groupDirective)) {
|
||||||
|
this._groupDirective.addDirective(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
var c = this._control();
|
||||||
|
c.validator = Validators.compose([c.validator, this.validator]);
|
||||||
|
|
||||||
|
this._updateDomValue();
|
||||||
|
this._setUpUpdateControlValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateDomValue() { this.valueAccessor.writeValue(this._control().value); }
|
||||||
|
|
||||||
|
_setUpUpdateControlValue() {
|
||||||
|
this.valueAccessor.onChange = (newValue) => this._control().updateValue(newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
_control() { return _lookupControl(this._groupDirective, this._controlOrName); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The accessor for writing a value and listening to changes on a checkbox input element.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* # Example
|
||||||
|
* ```
|
||||||
|
* <input type="checkbox" [control]="rememberLogin">
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @exportedAs angular2/forms
|
||||||
|
*/
|
||||||
|
@Directive({
|
||||||
|
selector: 'input[type=checkbox][control]',
|
||||||
|
hostListeners: {'change': 'onChange($event.target.checked)'},
|
||||||
|
hostProperties: {'checked': 'checked'}
|
||||||
|
})
|
||||||
|
export class CheckboxControlValueAccessor {
|
||||||
|
_elementRef: ElementRef;
|
||||||
|
_renderer: Renderer;
|
||||||
|
|
||||||
|
checked: boolean;
|
||||||
|
onChange: Function;
|
||||||
|
|
||||||
|
constructor(cd: ControlDirective, elementRef: ElementRef, renderer: Renderer) {
|
||||||
|
this.onChange = (_) => {};
|
||||||
|
this._elementRef = elementRef;
|
||||||
|
this._renderer = renderer;
|
||||||
|
cd.valueAccessor = this; // ControlDirective should inject CheckboxControlDirective
|
||||||
|
}
|
||||||
|
|
||||||
|
writeValue(value) {
|
||||||
|
this._renderer.setElementProperty(this._elementRef.parentView.render,
|
||||||
|
this._elementRef.boundElementIndex, 'checked', value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* A list of all the form directives used as part of a `@View` annotation.
|
* A list of all the form directives used as part of a `@View` annotation.
|
||||||
@ -270,6 +246,5 @@ export class ControlGroupDirective {
|
|||||||
*
|
*
|
||||||
* @exportedAs angular2/forms
|
* @exportedAs angular2/forms
|
||||||
*/
|
*/
|
||||||
export const formDirectives:List = CONST_EXPR([
|
export const formDirectives: List<Type> = CONST_EXPR(
|
||||||
ControlGroupDirective, ControlDirective, CheckboxControlValueAccessor, DefaultValueAccessor
|
[ControlGroupDirective, ControlDirective, CheckboxControlValueAccessor, DefaultValueAccessor]);
|
||||||
]);
|
|
@ -51,7 +51,8 @@ import * as modelModule from './model';
|
|||||||
* bootstrap(LoginComp)
|
* bootstrap(LoginComp)
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* This example creates a {@link ControlGroup} that consists of a `login` {@link Control}, and a nested
|
* This example creates a {@link ControlGroup} that consists of a `login` {@link Control}, and a
|
||||||
|
* nested
|
||||||
* {@link ControlGroup} that defines a `password` and a `passwordConfirmation` {@link Control}:
|
* {@link ControlGroup} that defines a `password` and a `passwordConfirmation` {@link Control}:
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
@ -68,7 +69,8 @@ import * as modelModule from './model';
|
|||||||
* @exportedAs angular2/forms
|
* @exportedAs angular2/forms
|
||||||
*/
|
*/
|
||||||
export class FormBuilder {
|
export class FormBuilder {
|
||||||
group(controlsConfig, extra = null):modelModule.ControlGroup {
|
group(controlsConfig: StringMap<string, any>,
|
||||||
|
extra: StringMap<string, any> = null): modelModule.ControlGroup {
|
||||||
var controls = this._reduceControls(controlsConfig);
|
var controls = this._reduceControls(controlsConfig);
|
||||||
var optionals = isPresent(extra) ? StringMapWrapper.get(extra, "optionals") : null;
|
var optionals = isPresent(extra) ? StringMapWrapper.get(extra, "optionals") : null;
|
||||||
var validator = isPresent(extra) ? StringMapWrapper.get(extra, "validator") : null;
|
var validator = isPresent(extra) ? StringMapWrapper.get(extra, "validator") : null;
|
||||||
@ -80,7 +82,7 @@ export class FormBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
control(value, validator:Function = null):modelModule.Control {
|
control(value: Object, validator: Function = null): modelModule.Control {
|
||||||
if (isPresent(validator)) {
|
if (isPresent(validator)) {
|
||||||
return new modelModule.Control(value, validator);
|
return new modelModule.Control(value, validator);
|
||||||
} else {
|
} else {
|
||||||
@ -88,7 +90,7 @@ export class FormBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
array(controlsConfig:List, validator:Function = null):modelModule.ControlArray {
|
array(controlsConfig: List<any>, validator: Function = null): modelModule.ControlArray {
|
||||||
var controls = ListWrapper.map(controlsConfig, (c) => this._createControl(c));
|
var controls = ListWrapper.map(controlsConfig, (c) => this._createControl(c));
|
||||||
if (isPresent(validator)) {
|
if (isPresent(validator)) {
|
||||||
return new modelModule.ControlArray(controls, validator);
|
return new modelModule.ControlArray(controls, validator);
|
||||||
@ -97,7 +99,7 @@ export class FormBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_reduceControls(controlsConfig) {
|
_reduceControls(controlsConfig: any): StringMap<string, modelModule.AbstractControl> {
|
||||||
var controls = {};
|
var controls = {};
|
||||||
StringMapWrapper.forEach(controlsConfig, (controlConfig, controlName) => {
|
StringMapWrapper.forEach(controlsConfig, (controlConfig, controlName) => {
|
||||||
controls[controlName] = this._createControl(controlConfig);
|
controls[controlName] = this._createControl(controlConfig);
|
||||||
@ -105,10 +107,10 @@ export class FormBuilder {
|
|||||||
return controls;
|
return controls;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createControl(controlConfig) {
|
_createControl(controlConfig: any): modelModule.AbstractControl {
|
||||||
if (controlConfig instanceof modelModule.Control ||
|
if (controlConfig instanceof modelModule.Control || controlConfig instanceof
|
||||||
controlConfig instanceof modelModule.ControlGroup ||
|
modelModule.ControlGroup || controlConfig instanceof
|
||||||
controlConfig instanceof modelModule.ControlArray) {
|
modelModule.ControlArray) {
|
||||||
return controlConfig;
|
return controlConfig;
|
||||||
|
|
||||||
} else if (ListWrapper.isList(controlConfig)) {
|
} else if (ListWrapper.isList(controlConfig)) {
|
@ -17,19 +17,7 @@ export const VALID = "VALID";
|
|||||||
*/
|
*/
|
||||||
export const INVALID = "INVALID";
|
export const INVALID = "INVALID";
|
||||||
|
|
||||||
//interface IControl {
|
export function isControl(c: Object): boolean {
|
||||||
// get value():any;
|
|
||||||
// validator:Function;
|
|
||||||
// get status():string;
|
|
||||||
// get valid():boolean;
|
|
||||||
// get errors():Map;
|
|
||||||
// get pristine():boolean;
|
|
||||||
// get dirty():boolean;
|
|
||||||
// updateValue(value:any){}
|
|
||||||
// setParent(parent){}
|
|
||||||
//}
|
|
||||||
|
|
||||||
export function isControl(c:Object):boolean {
|
|
||||||
return c instanceof AbstractControl;
|
return c instanceof AbstractControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,55 +25,39 @@ export function isControl(c:Object):boolean {
|
|||||||
/**
|
/**
|
||||||
* Omitting from external API doc as this is really an abstract internal concept.
|
* Omitting from external API doc as this is really an abstract internal concept.
|
||||||
*/
|
*/
|
||||||
class AbstractControl {
|
export class AbstractControl {
|
||||||
_value:any;
|
_value: any;
|
||||||
_status:string;
|
_status: string;
|
||||||
_errors:StringMap;
|
_errors: StringMap<string, any>;
|
||||||
_pristine:boolean;
|
_pristine: boolean;
|
||||||
_parent:any; /* ControlGroup | ControlArray */
|
_parent: any; /* ControlGroup | ControlArray */
|
||||||
validator:Function;
|
validator: Function;
|
||||||
|
|
||||||
_valueChanges:EventEmitter;
|
_valueChanges: EventEmitter;
|
||||||
|
|
||||||
constructor(validator:Function) {
|
constructor(validator: Function) {
|
||||||
this.validator = validator;
|
this.validator = validator;
|
||||||
this._pristine = true;
|
this._pristine = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
get value():any {
|
get value(): any { return this._value; }
|
||||||
return this._value;
|
|
||||||
}
|
|
||||||
|
|
||||||
get status():string {
|
get status(): string { return this._status; }
|
||||||
return this._status;
|
|
||||||
}
|
|
||||||
|
|
||||||
get valid():boolean {
|
get valid(): boolean { return this._status === VALID; }
|
||||||
return this._status === VALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
get errors():StringMap {
|
get errors(): StringMap<string, any> { return this._errors; }
|
||||||
return this._errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
get pristine():boolean {
|
get pristine(): boolean { return this._pristine; }
|
||||||
return this._pristine;
|
|
||||||
}
|
|
||||||
|
|
||||||
get dirty():boolean {
|
get dirty(): boolean { return !this.pristine; }
|
||||||
return ! this.pristine;
|
|
||||||
}
|
|
||||||
|
|
||||||
get valueChanges():Observable {
|
get valueChanges(): Observable { return this._valueChanges; }
|
||||||
return this._valueChanges;
|
|
||||||
}
|
|
||||||
|
|
||||||
setParent(parent){
|
setParent(parent) { this._parent = parent; }
|
||||||
this._parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateParent() {
|
_updateParent() {
|
||||||
if (isPresent(this._parent)){
|
if (isPresent(this._parent)) {
|
||||||
this._parent._updateValue();
|
this._parent._updateValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,19 +66,20 @@ class AbstractControl {
|
|||||||
/**
|
/**
|
||||||
* Defines a part of a form that cannot be divided into other controls.
|
* Defines a part of a form that cannot be divided into other controls.
|
||||||
*
|
*
|
||||||
* `Control` is one of the three fundamental building blocks used to define forms in Angular, along with
|
* `Control` is one of the three fundamental building blocks used to define forms in Angular, along
|
||||||
|
* with
|
||||||
* {@link ControlGroup} and {@link ControlArray}.
|
* {@link ControlGroup} and {@link ControlArray}.
|
||||||
*
|
*
|
||||||
* @exportedAs angular2/forms
|
* @exportedAs angular2/forms
|
||||||
*/
|
*/
|
||||||
export class Control extends AbstractControl {
|
export class Control extends AbstractControl {
|
||||||
constructor(value:any, validator:Function = Validators.nullValidator) {
|
constructor(value: any, validator: Function = Validators.nullValidator) {
|
||||||
super(validator);
|
super(validator);
|
||||||
this._setValueErrorsStatus(value);
|
this._setValueErrorsStatus(value);
|
||||||
this._valueChanges = new EventEmitter();
|
this._valueChanges = new EventEmitter();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateValue(value:any):void {
|
updateValue(value: any): void {
|
||||||
this._setValueErrorsStatus(value);
|
this._setValueErrorsStatus(value);
|
||||||
this._pristine = false;
|
this._pristine = false;
|
||||||
|
|
||||||
@ -115,7 +88,7 @@ export class Control extends AbstractControl {
|
|||||||
this._updateParent();
|
this._updateParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
_setValueErrorsStatus(value) {
|
_setValueErrorsStatus(value) {
|
||||||
this._value = value;
|
this._value = value;
|
||||||
this._errors = this.validator(this);
|
this._errors = this.validator(this);
|
||||||
this._status = isPresent(this._errors) ? INVALID : VALID;
|
this._status = isPresent(this._errors) ? INVALID : VALID;
|
||||||
@ -125,21 +98,27 @@ export class Control extends AbstractControl {
|
|||||||
/**
|
/**
|
||||||
* Defines a part of a form, of fixed length, that can contain other controls.
|
* Defines a part of a form, of fixed length, that can contain other controls.
|
||||||
*
|
*
|
||||||
* A ControlGroup aggregates the values and errors of each {@link Control} in the group. Thus, if one of the controls
|
* A ControlGroup aggregates the values and errors of each {@link Control} in the group. Thus, if
|
||||||
* in a group is invalid, the entire group is invalid. Similarly, if a control changes its value, the entire group
|
* one of the controls
|
||||||
|
* in a group is invalid, the entire group is invalid. Similarly, if a control changes its value,
|
||||||
|
* the entire group
|
||||||
* changes as well.
|
* changes as well.
|
||||||
*
|
*
|
||||||
* `ControlGroup` is one of the three fundamental building blocks used to define forms in Angular, along with
|
* `ControlGroup` is one of the three fundamental building blocks used to define forms in Angular,
|
||||||
* {@link Control} and {@link ControlArray}. {@link ControlArray} can also contain other controls, but is of variable
|
* along with
|
||||||
|
* {@link Control} and {@link ControlArray}. {@link ControlArray} can also contain other controls,
|
||||||
|
* but is of variable
|
||||||
* length.
|
* length.
|
||||||
*
|
*
|
||||||
* @exportedAs angular2/forms
|
* @exportedAs angular2/forms
|
||||||
*/
|
*/
|
||||||
export class ControlGroup extends AbstractControl {
|
export class ControlGroup extends AbstractControl {
|
||||||
controls:StringMap;
|
controls: StringMap<string, AbstractControl>;
|
||||||
_optionals:StringMap;
|
_optionals: StringMap<string, boolean>;
|
||||||
|
|
||||||
constructor(controls:StringMap, optionals:StringMap = null, validator:Function = Validators.group) {
|
constructor(controls: StringMap<String, AbstractControl>,
|
||||||
|
optionals: StringMap<String, boolean> = null,
|
||||||
|
validator: Function = Validators.group) {
|
||||||
super(validator);
|
super(validator);
|
||||||
this.controls = controls;
|
this.controls = controls;
|
||||||
this._optionals = isPresent(optionals) ? optionals : {};
|
this._optionals = isPresent(optionals) ? optionals : {};
|
||||||
@ -150,25 +129,23 @@ export class ControlGroup extends AbstractControl {
|
|||||||
this._setValueErrorsStatus();
|
this._setValueErrorsStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
include(controlName:string):void {
|
include(controlName: string): void {
|
||||||
StringMapWrapper.set(this._optionals, controlName, true);
|
StringMapWrapper.set(this._optionals, controlName, true);
|
||||||
this._updateValue();
|
this._updateValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
exclude(controlName:string):void {
|
exclude(controlName: string): void {
|
||||||
StringMapWrapper.set(this._optionals, controlName, false);
|
StringMapWrapper.set(this._optionals, controlName, false);
|
||||||
this._updateValue();
|
this._updateValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
contains(controlName:string):boolean {
|
contains(controlName: string): boolean {
|
||||||
var c = StringMapWrapper.contains(this.controls, controlName);
|
var c = StringMapWrapper.contains(this.controls, controlName);
|
||||||
return c && this._included(controlName);
|
return c && this._included(controlName);
|
||||||
}
|
}
|
||||||
|
|
||||||
_setParentForControls() {
|
_setParentForControls() {
|
||||||
StringMapWrapper.forEach(this.controls, (control, name) => {
|
StringMapWrapper.forEach(this.controls, (control, name) => { control.setParent(this); });
|
||||||
control.setParent(this);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateValue() {
|
_updateValue() {
|
||||||
@ -180,7 +157,7 @@ export class ControlGroup extends AbstractControl {
|
|||||||
this._updateParent();
|
this._updateParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
_setValueErrorsStatus() {
|
_setValueErrorsStatus() {
|
||||||
this._value = this._reduceValue();
|
this._value = this._reduceValue();
|
||||||
this._errors = this.validator(this);
|
this._errors = this.validator(this);
|
||||||
this._status = isPresent(this._errors) ? INVALID : VALID;
|
this._status = isPresent(this._errors) ? INVALID : VALID;
|
||||||
@ -193,7 +170,7 @@ export class ControlGroup extends AbstractControl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_reduceChildren(initValue:any, fn:Function) {
|
_reduceChildren(initValue: any, fn: Function) {
|
||||||
var res = initValue;
|
var res = initValue;
|
||||||
StringMapWrapper.forEach(this.controls, (control, name) => {
|
StringMapWrapper.forEach(this.controls, (control, name) => {
|
||||||
if (this._included(name)) {
|
if (this._included(name)) {
|
||||||
@ -203,7 +180,7 @@ export class ControlGroup extends AbstractControl {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
_included(controlName:string):boolean {
|
_included(controlName: string): boolean {
|
||||||
var isOptional = StringMapWrapper.contains(this._optionals, controlName);
|
var isOptional = StringMapWrapper.contains(this._optionals, controlName);
|
||||||
return !isOptional || StringMapWrapper.get(this._optionals, controlName);
|
return !isOptional || StringMapWrapper.get(this._optionals, controlName);
|
||||||
}
|
}
|
||||||
@ -212,20 +189,24 @@ export class ControlGroup extends AbstractControl {
|
|||||||
/**
|
/**
|
||||||
* Defines a part of a form, of variable length, that can contain other controls.
|
* Defines a part of a form, of variable length, that can contain other controls.
|
||||||
*
|
*
|
||||||
* A `ControlArray` aggregates the values and errors of each {@link Control} in the group. Thus, if one of the controls
|
* A `ControlArray` aggregates the values and errors of each {@link Control} in the group. Thus, if
|
||||||
* in a group is invalid, the entire group is invalid. Similarly, if a control changes its value, the entire group
|
* one of the controls
|
||||||
|
* in a group is invalid, the entire group is invalid. Similarly, if a control changes its value,
|
||||||
|
* the entire group
|
||||||
* changes as well.
|
* changes as well.
|
||||||
*
|
*
|
||||||
* `ControlArray` is one of the three fundamental building blocks used to define forms in Angular, along with
|
* `ControlArray` is one of the three fundamental building blocks used to define forms in Angular,
|
||||||
* {@link Control} and {@link ControlGroup}. {@link ControlGroup} can also contain other controls, but is of fixed
|
* along with
|
||||||
|
* {@link Control} and {@link ControlGroup}. {@link ControlGroup} can also contain other controls,
|
||||||
|
* but is of fixed
|
||||||
* length.
|
* length.
|
||||||
*
|
*
|
||||||
* @exportedAs angular2/forms
|
* @exportedAs angular2/forms
|
||||||
*/
|
*/
|
||||||
export class ControlArray extends AbstractControl {
|
export class ControlArray extends AbstractControl {
|
||||||
controls:List;
|
controls: List<AbstractControl>;
|
||||||
|
|
||||||
constructor(controls:List<AbstractControl>, validator:Function = Validators.array) {
|
constructor(controls: List<AbstractControl>, validator: Function = Validators.array) {
|
||||||
super(validator);
|
super(validator);
|
||||||
this.controls = controls;
|
this.controls = controls;
|
||||||
|
|
||||||
@ -235,30 +216,26 @@ export class ControlArray extends AbstractControl {
|
|||||||
this._setValueErrorsStatus();
|
this._setValueErrorsStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
at(index:number):AbstractControl {
|
at(index: number): AbstractControl { return this.controls[index]; }
|
||||||
return this.controls[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
push(control:AbstractControl):void {
|
push(control: AbstractControl): void {
|
||||||
ListWrapper.push(this.controls, control);
|
ListWrapper.push(this.controls, control);
|
||||||
control.setParent(this);
|
control.setParent(this);
|
||||||
this._updateValue();
|
this._updateValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
insert(index:number, control:AbstractControl):void {
|
insert(index: number, control: AbstractControl): void {
|
||||||
ListWrapper.insert(this.controls, index, control);
|
ListWrapper.insert(this.controls, index, control);
|
||||||
control.setParent(this);
|
control.setParent(this);
|
||||||
this._updateValue();
|
this._updateValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAt(index:number):void {
|
removeAt(index: number): void {
|
||||||
ListWrapper.removeAt(this.controls, index);
|
ListWrapper.removeAt(this.controls, index);
|
||||||
this._updateValue();
|
this._updateValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
get length():number {
|
get length(): number { return this.controls.length; }
|
||||||
return this.controls.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateValue() {
|
_updateValue() {
|
||||||
this._setValueErrorsStatus();
|
this._setValueErrorsStatus();
|
||||||
@ -270,12 +247,10 @@ export class ControlArray extends AbstractControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_setParentForControls() {
|
_setParentForControls() {
|
||||||
ListWrapper.forEach(this.controls, (control) => {
|
ListWrapper.forEach(this.controls, (control) => { control.setParent(this); });
|
||||||
control.setParent(this);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_setValueErrorsStatus() {
|
_setValueErrorsStatus() {
|
||||||
this._value = ListWrapper.map(this.controls, (c) => c.value);
|
this._value = ListWrapper.map(this.controls, (c) => c.value);
|
||||||
this._errors = this.validator(this);
|
this._errors = this.validator(this);
|
||||||
this._status = isPresent(this._errors) ? INVALID : VALID;
|
this._status = isPresent(this._errors) ? INVALID : VALID;
|
@ -1,13 +1,11 @@
|
|||||||
import {Directive} from 'angular2/src/core/annotations_impl/annotations';
|
import {Directive} from 'angular2/src/core/annotations/decorators';
|
||||||
|
|
||||||
import {Validators} from './validators';
|
import {Validators} from './validators';
|
||||||
import {ControlDirective} from './directives';
|
import {ControlDirective} from './directives';
|
||||||
|
|
||||||
@Directive({
|
@Directive({selector: '[required]'})
|
||||||
selector: '[required]'
|
|
||||||
})
|
|
||||||
export class RequiredValidatorDirective {
|
export class RequiredValidatorDirective {
|
||||||
constructor(c:ControlDirective) {
|
constructor(c: ControlDirective) {
|
||||||
c.validator = Validators.compose([c.validator, Validators.required]);
|
c.validator = Validators.compose([c.validator, Validators.required]);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,16 +15,14 @@ import * as modelModule from './model';
|
|||||||
* @exportedAs angular2/forms
|
* @exportedAs angular2/forms
|
||||||
*/
|
*/
|
||||||
export class Validators {
|
export class Validators {
|
||||||
static required(c:modelModule.Control) {
|
static required(c: modelModule.Control): StringMap<string, boolean> {
|
||||||
return isBlank(c.value) || c.value == "" ? {"required": true} : null;
|
return isBlank(c.value) || c.value == "" ? {"required": true} : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nullValidator(c:any) {
|
static nullValidator(c: any): StringMap<string, boolean> { return null; }
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static compose(validators:List<Function>):Function {
|
static compose(validators: List<Function>): Function {
|
||||||
return function (c:modelModule.Control) {
|
return function(c: modelModule.Control) {
|
||||||
var res = ListWrapper.reduce(validators, (res, validator) => {
|
var res = ListWrapper.reduce(validators, (res, validator) => {
|
||||||
var errors = validator(c);
|
var errors = validator(c);
|
||||||
return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res;
|
return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res;
|
||||||
@ -33,7 +31,7 @@ export class Validators {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static group(c:modelModule.ControlGroup) {
|
static group(c: modelModule.ControlGroup): StringMap<string, boolean> {
|
||||||
var res = {};
|
var res = {};
|
||||||
StringMapWrapper.forEach(c.controls, (control, name) => {
|
StringMapWrapper.forEach(c.controls, (control, name) => {
|
||||||
if (c.contains(name) && isPresent(control.errors)) {
|
if (c.contains(name) && isPresent(control.errors)) {
|
||||||
@ -43,7 +41,7 @@ export class Validators {
|
|||||||
return StringMapWrapper.isEmpty(res) ? null : res;
|
return StringMapWrapper.isEmpty(res) ? null : res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static array(c:modelModule.ControlArray) {
|
static array(c: modelModule.ControlArray): StringMap<string, boolean> {
|
||||||
var res = {};
|
var res = {};
|
||||||
ListWrapper.forEach(c.controls, (control) => {
|
ListWrapper.forEach(c.controls, (control) => {
|
||||||
if (isPresent(control.errors)) {
|
if (isPresent(control.errors)) {
|
||||||
@ -53,7 +51,7 @@ export class Validators {
|
|||||||
return StringMapWrapper.isEmpty(res) ? null : res;
|
return StringMapWrapper.isEmpty(res) ? null : res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static _mergeErrors(control, res) {
|
static _mergeErrors(control: modelModule.AbstractControl, res: StringMap<string, any>): void {
|
||||||
StringMapWrapper.forEach(control.errors, (value, error) => {
|
StringMapWrapper.forEach(control.errors, (value, error) => {
|
||||||
if (!StringMapWrapper.contains(res, error)) {
|
if (!StringMapWrapper.contains(res, error)) {
|
||||||
res[error] = [];
|
res[error] = [];
|
@ -1,8 +1,7 @@
|
|||||||
import {global} from 'angular2/src/facade/lang';
|
import {global} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
export function makeDecorator(annotationCls) {
|
export function makeDecorator(annotationCls) {
|
||||||
return function() {
|
return function(... args) {
|
||||||
var args = arguments;
|
|
||||||
var Reflect = global.Reflect;
|
var Reflect = global.Reflect;
|
||||||
if (!(Reflect && Reflect.getMetadata)) {
|
if (!(Reflect && Reflect.getMetadata)) {
|
||||||
throw 'reflect-metadata shim is required when using class decorators';
|
throw 'reflect-metadata shim is required when using class decorators';
|
||||||
@ -19,7 +18,7 @@ export function makeDecorator(annotationCls) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeParamDecorator(annotationCls) {
|
export function makeParamDecorator(annotationCls): any {
|
||||||
return function(... args) {
|
return function(... args) {
|
||||||
var Reflect = global.Reflect;
|
var Reflect = global.Reflect;
|
||||||
if (!(Reflect && Reflect.getMetadata)) {
|
if (!(Reflect && Reflect.getMetadata)) {
|
||||||
@ -28,14 +27,19 @@ export function makeParamDecorator(annotationCls) {
|
|||||||
var annotationInstance = Object.create(annotationCls.prototype);
|
var annotationInstance = Object.create(annotationCls.prototype);
|
||||||
annotationCls.apply(annotationInstance, args);
|
annotationCls.apply(annotationInstance, args);
|
||||||
return function(cls, unusedKey, index) {
|
return function(cls, unusedKey, index) {
|
||||||
var parameters = Reflect.getMetadata('parameters', cls);
|
var parameters: Array<Array<any>> = Reflect.getMetadata('parameters', cls);
|
||||||
parameters = parameters || [];
|
parameters = parameters || [];
|
||||||
|
|
||||||
// there might be gaps if some in between parameters do not have annotations.
|
// there might be gaps if some in between parameters do not have annotations.
|
||||||
// we pad with nulls.
|
// we pad with nulls.
|
||||||
while (parameters.length <= index) {
|
while (parameters.length <= index) {
|
||||||
parameters.push(null);
|
parameters.push(null);
|
||||||
}
|
}
|
||||||
parameters[index] = annotationInstance;
|
|
||||||
|
parameters[index] = parameters[index] || [];
|
||||||
|
var annotationsForParam: Array<any> = parameters[index];
|
||||||
|
annotationsForParam.push(annotationInstance);
|
||||||
|
|
||||||
Reflect.defineMetadata('parameters', parameters, cls);
|
Reflect.defineMetadata('parameters', parameters, cls);
|
||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ export function main() {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
it("should update the control group values on DOM change",
|
it("should update the control group values on DOM change",
|
||||||
inject([TestBed, AsyncTestCompleter], (tb, async) => {
|
inject([TestBed, AsyncTestCompleter], (tb, async) => {
|
||||||
var form = new ControlGroup({
|
var form = new ControlGroup({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user