feat(forms): changed forms to capture submit events and fires synthetic ng-submit events
This commit is contained in:
parent
1a4d23742b
commit
5fc23caef7
|
@ -1,5 +1,7 @@
|
||||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
|
import {ObservableWrapper, EventEmitter} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
import {Directive, onChange} from 'angular2/angular2';
|
import {Directive, onChange} from 'angular2/angular2';
|
||||||
import {FORWARD_REF, Binding} from 'angular2/di';
|
import {FORWARD_REF, Binding} from 'angular2/di';
|
||||||
import {ControlDirective} from './control_directive';
|
import {ControlDirective} from './control_directive';
|
||||||
|
@ -57,11 +59,16 @@ const formDirectiveBinding = CONST_EXPR(
|
||||||
selector: '[ng-form-model]',
|
selector: '[ng-form-model]',
|
||||||
hostInjector: [formDirectiveBinding],
|
hostInjector: [formDirectiveBinding],
|
||||||
properties: ['form: ng-form-model'],
|
properties: ['form: ng-form-model'],
|
||||||
lifecycle: [onChange]
|
lifecycle: [onChange],
|
||||||
|
hostListeners: {
|
||||||
|
'submit': 'onSubmit()',
|
||||||
|
},
|
||||||
|
events: ['ngSubmit']
|
||||||
})
|
})
|
||||||
export class FormModelDirective extends ControlContainerDirective implements FormDirective {
|
export class FormModelDirective extends ControlContainerDirective implements FormDirective {
|
||||||
form: ControlGroup = null;
|
form: ControlGroup = null;
|
||||||
directives: List<ControlDirective>;
|
directives: List<ControlDirective>;
|
||||||
|
ngSubmit = new EventEmitter();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
@ -94,6 +101,11 @@ export class FormModelDirective extends ControlContainerDirective implements For
|
||||||
c.updateValue(value);
|
c.updateValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
ObservableWrapper.callNext(this.ngSubmit, null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
_updateDomValue() {
|
_updateDomValue() {
|
||||||
ListWrapper.forEach(this.directives, dir => {
|
ListWrapper.forEach(this.directives, dir => {
|
||||||
var c: any = this.form.find(dir.path);
|
var c: any = this.form.find(dir.path);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {PromiseWrapper} from 'angular2/src/facade/async';
|
import {PromiseWrapper, ObservableWrapper, EventEmitter} from 'angular2/src/facade/async';
|
||||||
import {StringMapWrapper, List, ListWrapper} from 'angular2/src/facade/collection';
|
import {StringMapWrapper, List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {isPresent, CONST_EXPR} from 'angular2/src/facade/lang';
|
import {isPresent, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||||
import {Directive} from 'angular2/src/core/annotations/decorators';
|
import {Directive} from 'angular2/src/core/annotations/decorators';
|
||||||
|
@ -15,11 +15,16 @@ const formDirectiveBinding = CONST_EXPR(new Binding(
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'form:not([ng-no-form]):not([ng-form-model]),ng-form,[ng-form]',
|
selector: 'form:not([ng-no-form]):not([ng-form-model]),ng-form,[ng-form]',
|
||||||
hostInjector: [formDirectiveBinding]
|
hostInjector: [formDirectiveBinding],
|
||||||
|
hostListeners: {
|
||||||
|
'submit': 'onSubmit()',
|
||||||
|
},
|
||||||
|
events: ['ngSubmit']
|
||||||
})
|
})
|
||||||
export class TemplateDrivenFormDirective extends ControlContainerDirective implements
|
export class TemplateDrivenFormDirective extends ControlContainerDirective implements
|
||||||
FormDirective {
|
FormDirective {
|
||||||
form: ControlGroup;
|
form: ControlGroup;
|
||||||
|
ngSubmit = new EventEmitter();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
@ -34,12 +39,15 @@ export class TemplateDrivenFormDirective extends ControlContainerDirective imple
|
||||||
|
|
||||||
get value(): any { return this.form.value; }
|
get value(): any { return this.form.value; }
|
||||||
|
|
||||||
|
get errors(): any { return this.form.errors; }
|
||||||
|
|
||||||
addControl(dir: ControlDirective): void {
|
addControl(dir: ControlDirective): void {
|
||||||
this._later(_ => {
|
this._later(_ => {
|
||||||
var group = this._findContainer(dir.path);
|
var container = this._findContainer(dir.path);
|
||||||
var c = new Control("");
|
var c = new Control("");
|
||||||
setUpControl(c, dir);
|
setUpControl(c, dir);
|
||||||
group.addControl(dir.name, c);
|
container.addControl(dir.name, c);
|
||||||
|
c.updateValidity();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,23 +55,28 @@ export class TemplateDrivenFormDirective extends ControlContainerDirective imple
|
||||||
|
|
||||||
removeControl(dir: ControlDirective): void {
|
removeControl(dir: ControlDirective): void {
|
||||||
this._later(_ => {
|
this._later(_ => {
|
||||||
var c = this._findContainer(dir.path);
|
var container = this._findContainer(dir.path);
|
||||||
if (isPresent(c)) c.removeControl(dir.name)
|
if (isPresent(container)) {
|
||||||
|
container.removeControl(dir.name) container.updateValidity();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addControlGroup(dir: ControlGroupDirective): void {
|
addControlGroup(dir: ControlGroupDirective): void {
|
||||||
this._later(_ => {
|
this._later(_ => {
|
||||||
var group = this._findContainer(dir.path);
|
var container = this._findContainer(dir.path);
|
||||||
var c = new ControlGroup({});
|
var c = new ControlGroup({});
|
||||||
group.addControl(dir.name, c);
|
container.addControl(dir.name, c);
|
||||||
|
c.updateValidity();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeControlGroup(dir: ControlGroupDirective): void {
|
removeControlGroup(dir: ControlGroupDirective): void {
|
||||||
this._later(_ => {
|
this._later(_ => {
|
||||||
var c = this._findContainer(dir.path);
|
var container = this._findContainer(dir.path);
|
||||||
if (isPresent(c)) c.removeControl(dir.name)
|
if (isPresent(container)) {
|
||||||
|
container.removeControl(dir.name) container.updateValidity();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +87,11 @@ export class TemplateDrivenFormDirective extends ControlContainerDirective imple
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
ObservableWrapper.callNext(this.ngSubmit, null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
_findContainer(path: List<string>): ControlGroup {
|
_findContainer(path: List<string>): ControlGroup {
|
||||||
ListWrapper.removeLast(path);
|
ListWrapper.removeLast(path);
|
||||||
return <ControlGroup>this.form.find(path);
|
return <ControlGroup>this.form.find(path);
|
||||||
|
|
|
@ -74,6 +74,25 @@ export function main() {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it("should emit ng-submit event on submit",
|
||||||
|
inject([TestBed], fakeAsync(tb => {
|
||||||
|
var form = new ControlGroup({});
|
||||||
|
var ctx = MyComp.create({form: form, name: 'old'});
|
||||||
|
|
||||||
|
var t =
|
||||||
|
`<div><form [ng-form-model]="form" (ng-submit)="name='updated'"></form></div>`;
|
||||||
|
|
||||||
|
tb.createView(MyComp, {context: ctx, html: t})
|
||||||
|
.then((view) => {
|
||||||
|
var form = view.querySelector("form");
|
||||||
|
|
||||||
|
dispatchEvent(form, "submit");
|
||||||
|
tick();
|
||||||
|
|
||||||
|
expect(ctx.name).toEqual("updated");
|
||||||
|
});
|
||||||
|
})));
|
||||||
|
|
||||||
it("should work with single controls", inject([TestBed, AsyncTestCompleter], (tb, async) => {
|
it("should work with single controls", inject([TestBed, AsyncTestCompleter], (tb, async) => {
|
||||||
var control = new Control("loginValue");
|
var control = new Control("loginValue");
|
||||||
var ctx = MyComp.create({form: control});
|
var ctx = MyComp.create({form: control});
|
||||||
|
@ -473,6 +492,23 @@ export function main() {
|
||||||
});
|
});
|
||||||
})));
|
})));
|
||||||
|
|
||||||
|
it("should emit ng-submit event on submit",
|
||||||
|
inject([TestBed], fakeAsync(tb => {
|
||||||
|
var ctx = MyComp.create({name: 'old'});
|
||||||
|
|
||||||
|
var t = `<div><form (ng-submit)="name='updated'"></form></div>`;
|
||||||
|
|
||||||
|
tb.createView(MyComp, {context: ctx, html: t})
|
||||||
|
.then((view) => {
|
||||||
|
var form = view.querySelector("form");
|
||||||
|
|
||||||
|
dispatchEvent(form, "submit");
|
||||||
|
tick();
|
||||||
|
|
||||||
|
expect(ctx.name).toEqual("updated");
|
||||||
|
});
|
||||||
|
})));
|
||||||
|
|
||||||
it("should not create a template-driven form when ng-no-form is used",
|
it("should not create a template-driven form when ng-no-form is used",
|
||||||
inject([TestBed], fakeAsync(tb => {
|
inject([TestBed], fakeAsync(tb => {
|
||||||
var ctx = MyComp.create({name: null});
|
var ctx = MyComp.create({name: null});
|
||||||
|
|
Loading…
Reference in New Issue