parent
73351ac00f
commit
d6cda15879
|
@ -40,7 +40,7 @@ export class CheckboxControlValueAccessor implements ControlValueAccessor {
|
||||||
cd.valueAccessor = this;
|
cd.valueAccessor = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeValue(value: any) { setProperty(this._renderer, this._elementRef, "checked", value); }
|
writeValue(value: any): void { setProperty(this._renderer, this._elementRef, "checked", value); }
|
||||||
|
|
||||||
get ngClassUntouched(): boolean {
|
get ngClassUntouched(): boolean {
|
||||||
return isPresent(this._cd.control) ? this._cd.control.untouched : false;
|
return isPresent(this._cd.control) ? this._cd.control.untouched : false;
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {Form} from './form_interface';
|
||||||
import {AbstractControlDirective} from './abstract_control_directive';
|
import {AbstractControlDirective} from './abstract_control_directive';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A directive that contains a group of [NgControl].
|
* A directive that contains multiple {@link NgControl}.
|
||||||
*
|
*
|
||||||
* Only used by the forms module.
|
* Only used by the forms module.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -41,9 +41,7 @@ export class DefaultValueAccessor implements ControlValueAccessor {
|
||||||
cd.valueAccessor = this;
|
cd.valueAccessor = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeValue(value: any) {
|
writeValue(value: any): void {
|
||||||
// both this.value and setProperty are required at the moment
|
|
||||||
// remove when a proper imperative API is provided
|
|
||||||
var normalizedValue = isBlank(value) ? '' : value;
|
var normalizedValue = isBlank(value) ? '' : value;
|
||||||
setProperty(this._renderer, this._elementRef, 'value', normalizedValue);
|
setProperty(this._renderer, this._elementRef, 'value', normalizedValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,8 @@ const controlGroupBinding =
|
||||||
* `})
|
* `})
|
||||||
* class SignupComp {
|
* class SignupComp {
|
||||||
* onSignUp(value) {
|
* onSignUp(value) {
|
||||||
* // value === {personal: {name: 'some name'},
|
* // value === {
|
||||||
|
* // personal: {name: 'some name'},
|
||||||
* // credentials: {login: 'some login', password: 'some password'}}
|
* // credentials: {login: 'some login', password: 'some password'}}
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
|
@ -63,9 +64,9 @@ export class NgControlGroup extends ControlContainer implements OnInit,
|
||||||
this._parent = _parent;
|
this._parent = _parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
onInit() { this.formDirective.addControlGroup(this); }
|
onInit(): void { this.formDirective.addControlGroup(this); }
|
||||||
|
|
||||||
onDestroy() { this.formDirective.removeControlGroup(this); }
|
onDestroy(): void { this.formDirective.removeControlGroup(this); }
|
||||||
|
|
||||||
get control(): ControlGroup { return this.formDirective.getControlGroup(this); }
|
get control(): ControlGroup { return this.formDirective.getControlGroup(this); }
|
||||||
|
|
||||||
|
|
|
@ -24,24 +24,23 @@ const controlNameBinding =
|
||||||
*
|
*
|
||||||
* In this example, we create the login and password controls.
|
* In this example, we create the login and password controls.
|
||||||
* We can work with each control separately: check its validity, get its value, listen to its
|
* We can work with each control separately: check its validity, get its value, listen to its
|
||||||
changes.
|
* changes.
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Component({selector: "login-comp"})
|
* @Component({selector: "login-comp"})
|
||||||
* @View({
|
* @View({
|
||||||
* directives: [FORM_DIRECTIVES],
|
* directives: [FORM_DIRECTIVES],
|
||||||
* template: `
|
* template: `
|
||||||
* <form #f="form" (submit)='onLogIn(f.value)'>
|
* <form #f="form" (submit)='onLogIn(f.value)'>
|
||||||
* Login <input type='text' ng-control='login' #l="form">
|
* Login <input type='text' ng-control='login' #l="form">
|
||||||
* <div *ng-if="!l.valid">Login is invalid</div>
|
* <div *ng-if="!l.valid">Login is invalid</div>
|
||||||
*
|
*
|
||||||
* Password <input type='password' ng-control='password'>
|
* Password <input type='password' ng-control='password'>
|
||||||
|
* <button type='submit'>Log in!</button>
|
||||||
* <button type='submit'>Log in!</button>
|
* </form>
|
||||||
* </form>
|
|
||||||
* `})
|
* `})
|
||||||
* class LoginComp {
|
* class LoginComp {
|
||||||
* onLogIn(value) {
|
* onLogIn(value): void {
|
||||||
* // value === {login: 'some login', password: 'some password'}
|
* // value === {login: 'some login', password: 'some password'}
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
|
@ -54,17 +53,17 @@ const controlNameBinding =
|
||||||
* @View({
|
* @View({
|
||||||
* directives: [FORM_DIRECTIVES],
|
* directives: [FORM_DIRECTIVES],
|
||||||
* template: `
|
* template: `
|
||||||
* <form (submit)='onLogIn()'>
|
* <form (submit)='onLogIn()'>
|
||||||
* Login <input type='text' ng-control='login' [(ng-model)]="credentials.login">
|
* Login <input type='text' ng-control='login' [(ng-model)]="credentials.login">
|
||||||
* Password <input type='password' ng-control='password'
|
* Password <input type='password' ng-control='password'
|
||||||
[(ng-model)]="credentials.password">
|
* [(ng-model)]="credentials.password">
|
||||||
* <button type='submit'>Log in!</button>
|
* <button type='submit'>Log in!</button>
|
||||||
* </form>
|
* </form>
|
||||||
* `})
|
* `})
|
||||||
* class LoginComp {
|
* class LoginComp {
|
||||||
* credentials: {login:string, password:string};
|
* credentials: {login:string, password:string};
|
||||||
*
|
*
|
||||||
* onLogIn() {
|
* onLogIn(): void {
|
||||||
* // this.credentials.login === "some login"
|
* // this.credentials.login === "some login"
|
||||||
* // this.credentials.password === "some password"
|
* // this.credentials.password === "some password"
|
||||||
* }
|
* }
|
||||||
|
@ -94,18 +93,18 @@ export class NgControlName extends NgControl implements OnChanges,
|
||||||
this.validators = validators;
|
this.validators = validators;
|
||||||
}
|
}
|
||||||
|
|
||||||
onChanges(c: StringMap<string, any>) {
|
onChanges(changes: StringMap<string, any>) {
|
||||||
if (!this._added) {
|
if (!this._added) {
|
||||||
this.formDirective.addControl(this);
|
this.formDirective.addControl(this);
|
||||||
this._added = true;
|
this._added = true;
|
||||||
}
|
}
|
||||||
if (isPropertyUpdated(c, 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroy() { this.formDirective.removeControl(this); }
|
onDestroy(): void { this.formDirective.removeControl(this); }
|
||||||
|
|
||||||
viewToModelUpdate(newValue: any): void {
|
viewToModelUpdate(newValue: any): void {
|
||||||
this.viewModel = newValue;
|
this.viewModel = newValue;
|
||||||
|
|
|
@ -42,8 +42,9 @@ const formDirectiveBinding =
|
||||||
* </form>
|
* </form>
|
||||||
* `})
|
* `})
|
||||||
* class SignupComp {
|
* class SignupComp {
|
||||||
* onSignUp(value) {
|
* onSignUp(value): void {
|
||||||
* // value === {personal: {name: 'some name'},
|
* // value === {
|
||||||
|
* // personal: {name: 'some name'},
|
||||||
* // credentials: {login: 'some login', password: 'some password'}}
|
* // credentials: {login: 'some login', password: 'some password'}}
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
|
@ -60,14 +61,9 @@ const formDirectiveBinding =
|
||||||
exportAs: 'form'
|
exportAs: 'form'
|
||||||
})
|
})
|
||||||
export class NgForm extends ControlContainer implements Form {
|
export class NgForm extends ControlContainer implements Form {
|
||||||
form: ControlGroup;
|
form: ControlGroup = new ControlGroup({});
|
||||||
ngSubmit = new EventEmitter();
|
ngSubmit = new EventEmitter();
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.form = new ControlGroup({});
|
|
||||||
}
|
|
||||||
|
|
||||||
get formDirective(): Form { return this; }
|
get formDirective(): Form { return this; }
|
||||||
|
|
||||||
get control(): ControlGroup { return this.form; }
|
get control(): ControlGroup { return this.form; }
|
||||||
|
@ -79,10 +75,10 @@ export class NgForm extends ControlContainer implements Form {
|
||||||
addControl(dir: NgControl): void {
|
addControl(dir: NgControl): void {
|
||||||
this._later(_ => {
|
this._later(_ => {
|
||||||
var container = this._findContainer(dir.path);
|
var container = this._findContainer(dir.path);
|
||||||
var c = new Control();
|
var ctrl = new Control();
|
||||||
setUpControl(c, dir);
|
setUpControl(ctrl, dir);
|
||||||
container.addControl(dir.name, c);
|
container.addControl(dir.name, ctrl);
|
||||||
c.updateValidity();
|
ctrl.updateValidity();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,9 +97,9 @@ export class NgForm extends ControlContainer implements Form {
|
||||||
addControlGroup(dir: NgControlGroup): void {
|
addControlGroup(dir: NgControlGroup): void {
|
||||||
this._later(_ => {
|
this._later(_ => {
|
||||||
var container = this._findContainer(dir.path);
|
var container = this._findContainer(dir.path);
|
||||||
var c = new ControlGroup({});
|
var group = new ControlGroup({});
|
||||||
container.addControl(dir.name, c);
|
container.addControl(dir.name, group);
|
||||||
c.updateValidity();
|
group.updateValidity();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,8 +119,8 @@ export class NgForm extends ControlContainer implements Form {
|
||||||
|
|
||||||
updateModel(dir: NgControl, value: any): void {
|
updateModel(dir: NgControl, value: any): void {
|
||||||
this._later(_ => {
|
this._later(_ => {
|
||||||
var c = <Control>this.form.find(dir.path);
|
var ctrl = <Control>this.form.find(dir.path);
|
||||||
c.updateValue(value);
|
ctrl.updateValue(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,9 +134,5 @@ export class NgForm extends ControlContainer implements Form {
|
||||||
return ListWrapper.isEmpty(path) ? this.form : <ControlGroup>this.form.find(path);
|
return ListWrapper.isEmpty(path) ? this.form : <ControlGroup>this.form.find(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
_later(fn) {
|
_later(fn): void { PromiseWrapper.then(PromiseWrapper.resolve(null), fn, (_) => {}); }
|
||||||
var c: PromiseCompleter<any> = PromiseWrapper.completer();
|
|
||||||
PromiseWrapper.then(c.promise, fn, (_) => {});
|
|
||||||
c.resolve(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,8 @@ const formControlBinding =
|
||||||
* # Example
|
* # Example
|
||||||
*
|
*
|
||||||
* In this example, we bind the control to an input element. When the value of the input element
|
* In this example, we bind the control to an input element. When the value of the input element
|
||||||
* changes, the value of
|
* changes, the value of the control will reflect that change. Likewise, if the value of the
|
||||||
* the control will reflect that change. Likewise, if the value of the control changes, the input
|
* control changes, the input element reflects that change.
|
||||||
* element reflects that
|
|
||||||
* change.
|
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Component({selector: "login-comp"})
|
* @Component({selector: "login-comp"})
|
||||||
|
@ -29,16 +27,12 @@ const formControlBinding =
|
||||||
* template: "<input type='text' [ng-form-control]='loginControl'>"
|
* template: "<input type='text' [ng-form-control]='loginControl'>"
|
||||||
* })
|
* })
|
||||||
* class LoginComp {
|
* class LoginComp {
|
||||||
* loginControl:Control;
|
* loginControl: Control = new Control('');;
|
||||||
*
|
|
||||||
* constructor() {
|
|
||||||
* this.loginControl = new Control('');
|
|
||||||
* }
|
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* We can also use ng-model to bind a domain model to the form.
|
* We can also use `ng-model` to bind a domain model to the form.
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Component({selector: "login-comp"})
|
* @Component({selector: "login-comp"})
|
||||||
|
@ -47,12 +41,8 @@ const formControlBinding =
|
||||||
* template: "<input type='text' [ng-form-control]='loginControl' [(ng-model)]='login'>"
|
* template: "<input type='text' [ng-form-control]='loginControl' [(ng-model)]='login'>"
|
||||||
* })
|
* })
|
||||||
* class LoginComp {
|
* class LoginComp {
|
||||||
* loginControl:Control;
|
* loginControl: Control = new Control('');
|
||||||
* login:string;
|
* login:string;
|
||||||
*
|
|
||||||
* constructor() {
|
|
||||||
* this.loginControl = new Control('');
|
|
||||||
* }
|
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
@ -76,13 +66,13 @@ export class NgFormControl extends NgControl implements OnChanges {
|
||||||
this.validators = validators;
|
this.validators = validators;
|
||||||
}
|
}
|
||||||
|
|
||||||
onChanges(c: StringMap<string, any>) {
|
onChanges(changes: StringMap<string, any>): void {
|
||||||
if (!this._added) {
|
if (!this._added) {
|
||||||
setUpControl(this.form, this);
|
setUpControl(this.form, this);
|
||||||
this.form.updateValidity();
|
this.form.updateValidity();
|
||||||
this._added = true;
|
this._added = true;
|
||||||
}
|
}
|
||||||
if (isPropertyUpdated(c, 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,21 +21,21 @@ const formDirectiveBinding =
|
||||||
* # Example
|
* # Example
|
||||||
*
|
*
|
||||||
* In this example, we bind the control group to the form element, and we bind the login and
|
* In this example, we bind the control group to the form element, and we bind the login and
|
||||||
* password controls to the
|
* password controls to the login and password elements.
|
||||||
* login and password elements.
|
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Component({selector: "login-comp"})
|
* @Component({selector: "login-comp"})
|
||||||
* @View({
|
* @View({
|
||||||
* directives: [FORM_DIRECTIVES],
|
* directives: [FORM_DIRECTIVES],
|
||||||
* template: "<form [ng-form-model]='loginForm'>" +
|
* template: `
|
||||||
* "Login <input type='text' ng-control='login'>" +
|
* <form [ng-form-model]='loginForm'>
|
||||||
* "Password <input type='password' ng-control='password'>" +
|
* Login <input type='text' ng-control='login'>
|
||||||
* "<button (click)="onLogin()">Login</button>" +
|
* Password <input type='password' ng-control='password'>
|
||||||
* "</form>"
|
* <button (click)="onLogin()">Login</button>
|
||||||
|
* </form>`
|
||||||
* })
|
* })
|
||||||
* class LoginComp {
|
* class LoginComp {
|
||||||
* loginForm:ControlGroup;
|
* loginForm: ControlGroup;
|
||||||
*
|
*
|
||||||
* constructor() {
|
* constructor() {
|
||||||
* this.loginForm = new ControlGroup({
|
* this.loginForm = new ControlGroup({
|
||||||
|
@ -44,7 +44,7 @@ const formDirectiveBinding =
|
||||||
* });
|
* });
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* onLogin() {
|
* onLogin(): void {
|
||||||
* // this.loginForm.value
|
* // this.loginForm.value
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
|
@ -57,15 +57,17 @@ const formDirectiveBinding =
|
||||||
* @Component({selector: "login-comp"})
|
* @Component({selector: "login-comp"})
|
||||||
* @View({
|
* @View({
|
||||||
* directives: [FORM_DIRECTIVES],
|
* directives: [FORM_DIRECTIVES],
|
||||||
* template: "<form [ng-form-model]='loginForm'>" +
|
* template: `
|
||||||
* "Login <input type='text' ng-control='login' [(ng-model)]='login'>" +
|
* <form [ng-form-model]='loginForm'>
|
||||||
* "Password <input type='password' ng-control='password' [(ng-model)]='password'>" +
|
* Login <input type='text' ng-control='login' [(ng-model)]='credentials.login'>
|
||||||
* "<button (click)="onLogin()">Login</button>" +
|
* Password <input type='password' ng-control='password'
|
||||||
* "</form>"
|
* [(ng-model)]='credentials.password'>
|
||||||
|
* <button (click)="onLogin()">Login</button>
|
||||||
|
* </form>`
|
||||||
* })
|
* })
|
||||||
* class LoginComp {
|
* class LoginComp {
|
||||||
* credentials:{login:string, password:string}
|
* credentials: {login: string, password: string};
|
||||||
* loginForm:ControlGroup;
|
* loginForm: ControlGroup;
|
||||||
*
|
*
|
||||||
* constructor() {
|
* constructor() {
|
||||||
* this.loginForm = new ControlGroup({
|
* this.loginForm = new ControlGroup({
|
||||||
|
@ -74,7 +76,7 @@ const formDirectiveBinding =
|
||||||
* });
|
* });
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* onLogin() {
|
* onLogin(): void {
|
||||||
* // this.credentials.login === 'some login'
|
* // this.credentials.login === 'some login'
|
||||||
* // this.credentials.password === 'some password'
|
* // this.credentials.password === 'some password'
|
||||||
* }
|
* }
|
||||||
|
@ -85,9 +87,7 @@ const formDirectiveBinding =
|
||||||
selector: '[ng-form-model]',
|
selector: '[ng-form-model]',
|
||||||
bindings: [formDirectiveBinding],
|
bindings: [formDirectiveBinding],
|
||||||
properties: ['form: ng-form-model'],
|
properties: ['form: ng-form-model'],
|
||||||
host: {
|
host: {'(submit)': 'onSubmit()'},
|
||||||
'(submit)': 'onSubmit()',
|
|
||||||
},
|
|
||||||
events: ['ngSubmit'],
|
events: ['ngSubmit'],
|
||||||
exportAs: 'form'
|
exportAs: 'form'
|
||||||
})
|
})
|
||||||
|
@ -97,7 +97,7 @@ export class NgFormModel extends ControlContainer implements Form,
|
||||||
directives: NgControl[] = [];
|
directives: NgControl[] = [];
|
||||||
ngSubmit = new EventEmitter();
|
ngSubmit = new EventEmitter();
|
||||||
|
|
||||||
onChanges(_) { this._updateDomValue(); }
|
onChanges(_): void { this._updateDomValue(); }
|
||||||
|
|
||||||
get formDirective(): Form { return this; }
|
get formDirective(): Form { return this; }
|
||||||
|
|
||||||
|
@ -106,9 +106,9 @@ export class NgFormModel extends ControlContainer implements Form,
|
||||||
get path(): string[] { return []; }
|
get path(): string[] { return []; }
|
||||||
|
|
||||||
addControl(dir: NgControl): void {
|
addControl(dir: NgControl): void {
|
||||||
var c: any = this.form.find(dir.path);
|
var ctrl: any = this.form.find(dir.path);
|
||||||
setUpControl(c, dir);
|
setUpControl(ctrl, dir);
|
||||||
c.updateValidity();
|
ctrl.updateValidity();
|
||||||
this.directives.push(dir);
|
this.directives.push(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,8 +125,8 @@ export class NgFormModel extends ControlContainer implements Form,
|
||||||
}
|
}
|
||||||
|
|
||||||
updateModel(dir: NgControl, value: any): void {
|
updateModel(dir: NgControl, value: any): void {
|
||||||
var c = <Control>this.form.find(dir.path);
|
var ctrl = <Control>this.form.find(dir.path);
|
||||||
c.updateValue(value);
|
ctrl.updateValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit(): boolean {
|
onSubmit(): boolean {
|
||||||
|
@ -136,8 +136,8 @@ export class NgFormModel extends ControlContainer implements Form,
|
||||||
|
|
||||||
_updateDomValue() {
|
_updateDomValue() {
|
||||||
ListWrapper.forEach(this.directives, dir => {
|
ListWrapper.forEach(this.directives, dir => {
|
||||||
var c: any = this.form.find(dir.path);
|
var ctrl: any = this.form.find(dir.path);
|
||||||
dir.valueAccessor.writeValue(c.value);
|
dir.valueAccessor.writeValue(ctrl.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,8 @@ const formControlBinding = CONST_EXPR(new Binding(NgControl, {toAlias: forwardRe
|
||||||
* @Component({selector: "search-comp"})
|
* @Component({selector: "search-comp"})
|
||||||
* @View({
|
* @View({
|
||||||
* directives: [FORM_DIRECTIVES],
|
* directives: [FORM_DIRECTIVES],
|
||||||
* template: `
|
* template: `<input type='text' [(ng-model)]="searchQuery">`
|
||||||
<input type='text' [(ng-model)]="searchQuery">
|
* })
|
||||||
* `})
|
|
||||||
* class SearchComp {
|
* class SearchComp {
|
||||||
* searchQuery: string;
|
* searchQuery: string;
|
||||||
* }
|
* }
|
||||||
|
@ -48,14 +47,14 @@ export class NgModel extends NgControl implements OnChanges {
|
||||||
this.validators = validators;
|
this.validators = validators;
|
||||||
}
|
}
|
||||||
|
|
||||||
onChanges(c: StringMap<string, any>) {
|
onChanges(changes: StringMap<string, any>) {
|
||||||
if (!this._added) {
|
if (!this._added) {
|
||||||
setUpControl(this._control, this);
|
setUpControl(this._control, this);
|
||||||
this._control.updateValidity();
|
this._control.updateValidity();
|
||||||
this._added = true;
|
this._added = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPropertyUpdated(c, 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {isPresent} from 'angular2/src/core/facade/lang';
|
||||||
import {setProperty} from './shared';
|
import {setProperty} from './shared';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks <option> as dynamic, so Angular can be notified when options change.
|
* Marks `<option>` as dynamic, so Angular can be notified when options change.
|
||||||
*
|
*
|
||||||
* #Example:
|
* #Example:
|
||||||
*
|
*
|
||||||
|
@ -53,7 +53,7 @@ export class SelectControlValueAccessor implements ControlValueAccessor {
|
||||||
this._updateValueWhenListOfOptionsChanges(query);
|
this._updateValueWhenListOfOptionsChanges(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeValue(value: any) {
|
writeValue(value: any): void {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
setProperty(this._renderer, this._elementRef, "value", value);
|
setProperty(this._renderer, this._elementRef, "value", value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,25 +16,25 @@ export function controlPath(name: string, parent: ControlContainer): string[] {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setUpControl(c: Control, dir: NgControl) {
|
export function setUpControl(control: Control, dir: NgControl): void {
|
||||||
if (isBlank(c)) _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");
|
||||||
|
|
||||||
c.validator = Validators.compose([c.validator, dir.validator]);
|
control.validator = Validators.compose([control.validator, dir.validator]);
|
||||||
dir.valueAccessor.writeValue(c.value);
|
dir.valueAccessor.writeValue(control.value);
|
||||||
|
|
||||||
// view -> model
|
// view -> model
|
||||||
dir.valueAccessor.registerOnChange(newValue => {
|
dir.valueAccessor.registerOnChange(newValue => {
|
||||||
dir.viewToModelUpdate(newValue);
|
dir.viewToModelUpdate(newValue);
|
||||||
c.updateValue(newValue, {emitModelToViewChange: false});
|
control.updateValue(newValue, {emitModelToViewChange: false});
|
||||||
c.markAsDirty();
|
control.markAsDirty();
|
||||||
});
|
});
|
||||||
|
|
||||||
// model -> view
|
// model -> view
|
||||||
c.registerOnChange(newValue => dir.valueAccessor.writeValue(newValue));
|
control.registerOnChange(newValue => dir.valueAccessor.writeValue(newValue));
|
||||||
|
|
||||||
// touched
|
// touched
|
||||||
dir.valueAccessor.registerOnTouched(() => c.markAsTouched());
|
dir.valueAccessor.registerOnTouched(() => control.markAsTouched());
|
||||||
}
|
}
|
||||||
|
|
||||||
function _throwError(dir: NgControl, message: string): void {
|
function _throwError(dir: NgControl, message: string): void {
|
||||||
|
@ -53,4 +53,4 @@ export function isPropertyUpdated(changes: StringMap<string, any>, viewModel: an
|
||||||
|
|
||||||
if (change.isFirstChange()) return true;
|
if (change.isFirstChange()) return true;
|
||||||
return !looseIdentical(viewModel, change.currentValue);
|
return !looseIdentical(viewModel, change.currentValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,7 @@ import * as modelModule from './model';
|
||||||
*
|
*
|
||||||
* @Component({
|
* @Component({
|
||||||
* selector: 'login-comp',
|
* selector: 'login-comp',
|
||||||
* viewBindings: [
|
* viewBindings: [FormBuilder]
|
||||||
* FormBuilder
|
|
||||||
* ]
|
|
||||||
* })
|
* })
|
||||||
* @View({
|
* @View({
|
||||||
* template: `
|
* template: `
|
||||||
|
@ -30,9 +28,7 @@ import * as modelModule from './model';
|
||||||
* </div>
|
* </div>
|
||||||
* </form>
|
* </form>
|
||||||
* `,
|
* `,
|
||||||
* directives: [
|
* directives: [FORM_DIRECTIVES]
|
||||||
* FORM_DIRECTIVES
|
|
||||||
* ]
|
|
||||||
* })
|
* })
|
||||||
* class LoginComp {
|
* class LoginComp {
|
||||||
* loginForm: ControlGroup;
|
* loginForm: ControlGroup;
|
||||||
|
@ -49,12 +45,12 @@ import * as modelModule from './model';
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* bootstrap(LoginComp)
|
* bootstrap(LoginComp);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* This example creates a {@link ControlGroup} that consists of a `login` {@link Control}, and a
|
* This example creates a {@link ControlGroup} that consists of a `login` {@link Control}, and a
|
||||||
* nested
|
* nested {@link ControlGroup} that defines a `password` and a `passwordConfirmation`
|
||||||
* {@link ControlGroup} that defines a `password` and a `passwordConfirmation` {@link Control}:
|
* {@link Control}:
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* var loginForm = builder.group({
|
* var loginForm = builder.group({
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {StringWrapper, isPresent, isBlank} from 'angular2/src/core/facade/lang';
|
import {StringWrapper, isPresent, isBlank, normalizeBool} from 'angular2/src/core/facade/lang';
|
||||||
import {Observable, EventEmitter, ObservableWrapper} from 'angular2/src/core/facade/async';
|
import {Observable, EventEmitter, ObservableWrapper} from 'angular2/src/core/facade/async';
|
||||||
import {StringMap, StringMapWrapper, ListWrapper} from 'angular2/src/core/facade/collection';
|
import {StringMap, StringMapWrapper, ListWrapper} from 'angular2/src/core/facade/collection';
|
||||||
import {Validators} from './validators';
|
import {Validators} from './validators';
|
||||||
|
@ -13,14 +13,15 @@ export const VALID = "VALID";
|
||||||
*/
|
*/
|
||||||
export const INVALID = "INVALID";
|
export const INVALID = "INVALID";
|
||||||
|
|
||||||
export function isControl(c: Object): boolean {
|
export function isControl(control: Object): boolean {
|
||||||
return c instanceof AbstractControl;
|
return control instanceof AbstractControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _find(c: 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 = StringWrapper.split(<string>path, new RegExp("/"));
|
path = (<string>path).split("/");
|
||||||
}
|
}
|
||||||
if (path instanceof Array && ListWrapper.isEmpty(path)) return null;
|
if (path instanceof Array && ListWrapper.isEmpty(path)) return null;
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ function _find(c: AbstractControl, path: Array<string | number>| string) {
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, c);
|
}, control);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,18 +44,13 @@ export class AbstractControl {
|
||||||
_value: any;
|
_value: any;
|
||||||
_status: string;
|
_status: string;
|
||||||
_errors: StringMap<string, any>;
|
_errors: StringMap<string, any>;
|
||||||
_pristine: boolean;
|
_pristine: boolean = true;
|
||||||
_touched: boolean;
|
_touched: boolean = false;
|
||||||
_parent: ControlGroup | ControlArray;
|
_parent: ControlGroup | ControlArray;
|
||||||
validator: Function;
|
|
||||||
|
|
||||||
_valueChanges: EventEmitter;
|
_valueChanges: EventEmitter;
|
||||||
|
|
||||||
constructor(validator: Function) {
|
constructor(public validator: Function) {}
|
||||||
this.validator = validator;
|
|
||||||
this._pristine = true;
|
|
||||||
this._touched = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
get value(): any { return this._value; }
|
get value(): any { return this._value; }
|
||||||
|
|
||||||
|
@ -77,18 +73,18 @@ export class AbstractControl {
|
||||||
markAsTouched(): void { this._touched = true; }
|
markAsTouched(): void { this._touched = true; }
|
||||||
|
|
||||||
markAsDirty({onlySelf}: {onlySelf?: boolean} = {}): void {
|
markAsDirty({onlySelf}: {onlySelf?: boolean} = {}): void {
|
||||||
onlySelf = isPresent(onlySelf) ? onlySelf : false;
|
onlySelf = normalizeBool(onlySelf);
|
||||||
|
|
||||||
this._pristine = false;
|
this._pristine = false;
|
||||||
|
|
||||||
if (isPresent(this._parent) && !onlySelf) {
|
if (isPresent(this._parent) && !onlySelf) {
|
||||||
this._parent.markAsDirty({onlySelf: onlySelf});
|
this._parent.markAsDirty({onlySelf: onlySelf});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setParent(parent: ControlGroup | ControlArray) { this._parent = parent; }
|
setParent(parent: ControlGroup | ControlArray): void { this._parent = parent; }
|
||||||
|
|
||||||
updateValidity({onlySelf}: {onlySelf?: boolean} = {}): void {
|
updateValidity({onlySelf}: {onlySelf?: boolean} = {}): void {
|
||||||
onlySelf = isPresent(onlySelf) ? onlySelf : false;
|
onlySelf = normalizeBool(onlySelf);
|
||||||
|
|
||||||
this._errors = this.validator(this);
|
this._errors = this.validator(this);
|
||||||
this._status = isPresent(this._errors) ? INVALID : VALID;
|
this._status = isPresent(this._errors) ? INVALID : VALID;
|
||||||
|
@ -100,7 +96,7 @@ export class AbstractControl {
|
||||||
|
|
||||||
updateValueAndValidity({onlySelf, emitEvent}: {onlySelf?: boolean, emitEvent?: boolean} = {}):
|
updateValueAndValidity({onlySelf, emitEvent}: {onlySelf?: boolean, emitEvent?: boolean} = {}):
|
||||||
void {
|
void {
|
||||||
onlySelf = isPresent(onlySelf) ? onlySelf : false;
|
onlySelf = normalizeBool(onlySelf);
|
||||||
emitEvent = isPresent(emitEvent) ? emitEvent : true;
|
emitEvent = isPresent(emitEvent) ? emitEvent : true;
|
||||||
|
|
||||||
this._updateValue();
|
this._updateValue();
|
||||||
|
@ -111,6 +107,7 @@ export class AbstractControl {
|
||||||
|
|
||||||
this._errors = this.validator(this);
|
this._errors = this.validator(this);
|
||||||
this._status = isPresent(this._errors) ? INVALID : VALID;
|
this._status = isPresent(this._errors) ? INVALID : VALID;
|
||||||
|
|
||||||
if (isPresent(this._parent) && !onlySelf) {
|
if (isPresent(this._parent) && !onlySelf) {
|
||||||
this._parent.updateValueAndValidity({onlySelf: onlySelf, emitEvent: emitEvent});
|
this._parent.updateValueAndValidity({onlySelf: onlySelf, emitEvent: emitEvent});
|
||||||
}
|
}
|
||||||
|
@ -119,9 +116,9 @@ export 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 c = isPresent(path) && !ListWrapper.isEmpty(path) ? this.find(path) : this;
|
var control = isPresent(path) && !ListWrapper.isEmpty(path) ? this.find(path) : this;
|
||||||
if (isPresent(c) && isPresent(c._errors)) {
|
if (isPresent(control) && isPresent(control._errors)) {
|
||||||
return StringMapWrapper.get(c._errors, errorCode);
|
return StringMapWrapper.get(control._errors, errorCode);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -138,8 +135,7 @@ export 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
|
* `Control` is one of the three fundamental building blocks used to define forms in Angular, along
|
||||||
* with
|
* with {@link ControlGroup} and {@link ControlArray}.
|
||||||
* {@link ControlGroup} and {@link ControlArray}.
|
|
||||||
*/
|
*/
|
||||||
export class Control extends AbstractControl {
|
export class Control extends AbstractControl {
|
||||||
_onChange: Function;
|
_onChange: Function;
|
||||||
|
@ -167,29 +163,22 @@ 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
|
* A `ControlGroup` aggregates the values and errors of each {@link Control} in the group. Thus, if
|
||||||
* one of the controls
|
* one of the controls in a group is invalid, the entire group is invalid. Similarly, if a control
|
||||||
* in a group is invalid, the entire group is invalid. Similarly, if a control changes its value,
|
* changes its value, the entire group changes as well.
|
||||||
* the entire group
|
|
||||||
* changes as well.
|
|
||||||
*
|
*
|
||||||
* `ControlGroup` is one of the three fundamental building blocks used to define forms in Angular,
|
* `ControlGroup` is one of the three fundamental building blocks used to define forms in Angular,
|
||||||
* along with
|
* along with {@link Control} and {@link ControlArray}. {@link ControlArray} can also contain other
|
||||||
* {@link Control} and {@link ControlArray}. {@link ControlArray} can also contain other controls,
|
* controls, but is of variable length.
|
||||||
* but is of variable
|
|
||||||
* length.
|
|
||||||
*/
|
*/
|
||||||
export class ControlGroup extends AbstractControl {
|
export class ControlGroup extends AbstractControl {
|
||||||
controls: StringMap<string, AbstractControl>;
|
private _optionals: StringMap<string, boolean>;
|
||||||
_optionals: StringMap<string, boolean>;
|
|
||||||
|
|
||||||
constructor(controls: StringMap<string, AbstractControl>,
|
constructor(public controls: StringMap<string, AbstractControl>,
|
||||||
optionals: StringMap<string, boolean> = null,
|
optionals: StringMap<string, boolean> = null,
|
||||||
validator: Function = Validators.group) {
|
validator: Function = Validators.group) {
|
||||||
super(validator);
|
super(validator);
|
||||||
this.controls = controls;
|
|
||||||
this._optionals = isPresent(optionals) ? optionals : {};
|
this._optionals = isPresent(optionals) ? optionals : {};
|
||||||
|
|
||||||
this._valueChanges = new EventEmitter();
|
this._valueChanges = new EventEmitter();
|
||||||
|
|
||||||
this._setParentForControls();
|
this._setParentForControls();
|
||||||
|
@ -197,12 +186,12 @@ export class ControlGroup extends AbstractControl {
|
||||||
this.updateValidity({onlySelf: true});
|
this.updateValidity({onlySelf: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
addControl(name: string, c: AbstractControl) {
|
addControl(name: string, control: AbstractControl): void {
|
||||||
this.controls[name] = c;
|
this.controls[name] = control;
|
||||||
c.setParent(this);
|
control.setParent(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeControl(name: string) { StringMapWrapper.delete(this.controls, name); }
|
removeControl(name: string): void { StringMapWrapper.delete(this.controls, name); }
|
||||||
|
|
||||||
include(controlName: string): void {
|
include(controlName: string): void {
|
||||||
StringMapWrapper.set(this._optionals, controlName, true);
|
StringMapWrapper.set(this._optionals, controlName, true);
|
||||||
|
@ -252,21 +241,16 @@ 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
|
* A `ControlArray` aggregates the values and errors of each {@link Control} in the group. Thus, if
|
||||||
* one of the controls
|
* one of the controls in a group is invalid, the entire group is invalid. Similarly, if a control
|
||||||
* in a group is invalid, the entire group is invalid. Similarly, if a control changes its value,
|
* changes its value, the entire group changes as well.
|
||||||
* the entire group
|
|
||||||
* changes as well.
|
|
||||||
*
|
*
|
||||||
* `ControlArray` is one of the three fundamental building blocks used to define forms in Angular,
|
* `ControlArray` is one of the three fundamental building blocks used to define forms in Angular,
|
||||||
* along with {@link Control} and {@link ControlGroup}. {@link ControlGroup} can also contain
|
* along with {@link Control} and {@link ControlGroup}. {@link ControlGroup} can also contain
|
||||||
* other controls, but is of fixed length.
|
* other controls, but is of fixed length.
|
||||||
*/
|
*/
|
||||||
export class ControlArray extends AbstractControl {
|
export class ControlArray extends AbstractControl {
|
||||||
controls: AbstractControl[];
|
constructor(public controls: AbstractControl[], validator: Function = Validators.array) {
|
||||||
|
|
||||||
constructor(controls: AbstractControl[], validator: Function = Validators.array) {
|
|
||||||
super(validator);
|
super(validator);
|
||||||
this.controls = controls;
|
|
||||||
|
|
||||||
this._valueChanges = new EventEmitter();
|
this._valueChanges = new EventEmitter();
|
||||||
|
|
||||||
|
@ -296,9 +280,9 @@ export class ControlArray extends AbstractControl {
|
||||||
|
|
||||||
get length(): number { return this.controls.length; }
|
get length(): number { return this.controls.length; }
|
||||||
|
|
||||||
_updateValue() { this._value = ListWrapper.map(this.controls, (c) => c.value); }
|
_updateValue(): void { this._value = this.controls.map((control) => control.value); }
|
||||||
|
|
||||||
_setParentForControls() {
|
_setParentForControls(): void {
|
||||||
ListWrapper.forEach(this.controls, (control) => { control.setParent(this); });
|
this.controls.forEach((control) => { control.setParent(this); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@ export const NG_VALIDATORS: OpaqueToken = CONST_EXPR(new OpaqueToken("NgValidato
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export class Validators {
|
export class Validators {
|
||||||
static required(c: modelModule.Control): StringMap<string, boolean> {
|
static required(control: modelModule.Control): StringMap<string, boolean> {
|
||||||
return isBlank(c.value) || c.value == "" ? {"required": true} : null;
|
return isBlank(control.value) || control.value == "" ? {"required": true} : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nullValidator(c: any): StringMap<string, boolean> { return null; }
|
static nullValidator(c: any): StringMap<string, boolean> { return null; }
|
||||||
|
@ -26,28 +26,28 @@ export class Validators {
|
||||||
static compose(validators: Function[]): Function {
|
static compose(validators: Function[]): Function {
|
||||||
if (isBlank(validators)) return Validators.nullValidator;
|
if (isBlank(validators)) return Validators.nullValidator;
|
||||||
|
|
||||||
return function(c: modelModule.Control) {
|
return function(control: modelModule.Control) {
|
||||||
var res = ListWrapper.reduce(validators, (res, validator) => {
|
var res = ListWrapper.reduce(validators, (res, validator) => {
|
||||||
var errors = validator(c);
|
var errors = validator(control);
|
||||||
return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res;
|
return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res;
|
||||||
}, {});
|
}, {});
|
||||||
return StringMapWrapper.isEmpty(res) ? null : res;
|
return StringMapWrapper.isEmpty(res) ? null : res;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static group(c: modelModule.ControlGroup): StringMap<string, boolean> {
|
static group(group: modelModule.ControlGroup): StringMap<string, boolean> {
|
||||||
var res = {};
|
var res = {};
|
||||||
StringMapWrapper.forEach(c.controls, (control, name) => {
|
StringMapWrapper.forEach(group.controls, (control, name) => {
|
||||||
if (c.contains(name) && isPresent(control.errors)) {
|
if (group.contains(name) && isPresent(control.errors)) {
|
||||||
Validators._mergeErrors(control, res);
|
Validators._mergeErrors(control, res);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return StringMapWrapper.isEmpty(res) ? null : res;
|
return StringMapWrapper.isEmpty(res) ? null : res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static array(c: modelModule.ControlArray): StringMap<string, boolean> {
|
static array(array: modelModule.ControlArray): StringMap<string, boolean> {
|
||||||
var res = {};
|
var res = {};
|
||||||
ListWrapper.forEach(c.controls, (control) => {
|
array.controls.forEach((control) => {
|
||||||
if (isPresent(control.errors)) {
|
if (isPresent(control.errors)) {
|
||||||
Validators._mergeErrors(control, res);
|
Validators._mergeErrors(control, res);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {RegExpWrapper, print, isPresent} from 'angular2/src/core/facade/lang';
|
||||||
* Custom validator.
|
* Custom validator.
|
||||||
*/
|
*/
|
||||||
function creditCardValidator(c): StringMap<string, boolean> {
|
function creditCardValidator(c): StringMap<string, boolean> {
|
||||||
if (isPresent(c.value) && RegExpWrapper.test(new RegExp("^\\d{16}$"), c.value)) {
|
if (isPresent(c.value) && RegExpWrapper.test(/^\d{16}$/g, c.value)) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return {"invalidCreditCard": true};
|
return {"invalidCreditCard": true};
|
||||||
|
@ -55,17 +55,19 @@ class ShowError {
|
||||||
|
|
||||||
constructor(@Host() formDir: NgFormModel) { this.formDir = formDir; }
|
constructor(@Host() formDir: NgFormModel) { this.formDir = formDir; }
|
||||||
|
|
||||||
get errorMessage() {
|
get errorMessage(): string {
|
||||||
var c = this.formDir.form.find(this.controlPath);
|
var control = this.formDir.form.find(this.controlPath);
|
||||||
for (var i = 0; i < this.errorTypes.length; ++i) {
|
if (isPresent(control) && control.touched) {
|
||||||
if (isPresent(c) && c.touched && c.hasError(this.errorTypes[i])) {
|
for (var i = 0; i < this.errorTypes.length; ++i) {
|
||||||
return this._errorMessage(this.errorTypes[i]);
|
if (control.hasError(this.errorTypes[i])) {
|
||||||
|
return this._errorMessage(this.errorTypes[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_errorMessage(code) {
|
_errorMessage(code: string): string {
|
||||||
var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'};
|
var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'};
|
||||||
return config[code];
|
return config[code];
|
||||||
}
|
}
|
||||||
|
@ -148,7 +150,7 @@ class ModelDrivenForms {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit(): void {
|
||||||
print("Submitting:");
|
print("Submitting:");
|
||||||
print(this.form.value);
|
print(this.form.value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ class CheckoutModel {
|
||||||
* Custom validator.
|
* Custom validator.
|
||||||
*/
|
*/
|
||||||
function creditCardValidator(c): StringMap<string, boolean> {
|
function creditCardValidator(c): StringMap<string, boolean> {
|
||||||
if (isPresent(c.value) && RegExpWrapper.test(new RegExp("^\\d{16}$"), c.value)) {
|
if (isPresent(c.value) && RegExpWrapper.test(/^\d{16}$/g, c.value)) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return {"invalidCreditCard": true};
|
return {"invalidCreditCard": true};
|
||||||
|
@ -79,17 +79,19 @@ class ShowError {
|
||||||
|
|
||||||
constructor(@Host() formDir: NgForm) { this.formDir = formDir; }
|
constructor(@Host() formDir: NgForm) { this.formDir = formDir; }
|
||||||
|
|
||||||
get errorMessage() {
|
get errorMessage(): string {
|
||||||
var c = this.formDir.form.find(this.controlPath);
|
var control = this.formDir.form.find(this.controlPath);
|
||||||
for (var i = 0; i < this.errorTypes.length; ++i) {
|
if (isPresent(control) && control.touched) {
|
||||||
if (isPresent(c) && c.touched && c.hasError(this.errorTypes[i])) {
|
for (var i = 0; i < this.errorTypes.length; ++i) {
|
||||||
return this._errorMessage(this.errorTypes[i]);
|
if (control.hasError(this.errorTypes[i])) {
|
||||||
|
return this._errorMessage(this.errorTypes[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_errorMessage(code) {
|
_errorMessage(code: string): string {
|
||||||
var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'};
|
var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'};
|
||||||
return config[code];
|
return config[code];
|
||||||
}
|
}
|
||||||
|
@ -159,7 +161,7 @@ class TemplateDrivenForms {
|
||||||
model = new CheckoutModel();
|
model = new CheckoutModel();
|
||||||
countries = ['US', 'Canada'];
|
countries = ['US', 'Canada'];
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit(): void {
|
||||||
print("Submitting:");
|
print("Submitting:");
|
||||||
print(this.model);
|
print(this.model);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue