From 17e3410d986d1d24dff0c4075ba3c82f9aedc89e Mon Sep 17 00:00:00 2001 From: Connor Wyatt Date: Tue, 11 Oct 2016 23:49:36 +0100 Subject: [PATCH] Form submit event (#11989) * feat(forms): ngSubmit event exposes $event from original submit event as local variable Modify NgForm directive and FormGroup directive to expose the original submit event as $event in the ngSubmit event. Modify docs to reflect changes. This resolves #10920. * refactor: code cleanup --- .../@angular/forms/src/directives/ng_form.ts | 19 ++++++++++--------- .../form_group_directive.ts | 16 ++++++++++------ .../forms/test/reactive_integration_spec.ts | 10 +++++----- .../forms/test/template_integration_spec.ts | 9 +++++---- tools/public_api_guard/forms/index.d.ts | 4 ++-- 5 files changed, 32 insertions(+), 26 deletions(-) diff --git a/modules/@angular/forms/src/directives/ng_form.ts b/modules/@angular/forms/src/directives/ng_form.ts index d6d7487efb..5951eb8886 100644 --- a/modules/@angular/forms/src/directives/ng_form.ts +++ b/modules/@angular/forms/src/directives/ng_form.ts @@ -48,7 +48,8 @@ const resolvedPromise = Promise.resolve(null); * sub-groups within the form. * * You can listen to the directive's `ngSubmit` event to be notified when the user has - * triggered a form submission. + * triggered a form submission. The `ngSubmit` event will be emitted with the original form + * submission event. * * {@example forms/ts/simpleForm/simple_form_example.ts region='Component'} * @@ -61,7 +62,7 @@ const resolvedPromise = Promise.resolve(null); @Directive({ selector: 'form:not([ngNoForm]):not([formGroup]),ngForm,[ngForm]', providers: [formDirectiveProvider], - host: {'(submit)': 'onSubmit()', '(reset)': 'onReset()'}, + host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'}, outputs: ['ngSubmit'], exportAs: 'ngForm' }) @@ -102,7 +103,7 @@ export class NgForm extends ControlContainer implements Form { removeControl(dir: NgModel): void { resolvedPromise.then(() => { - var container = this._findContainer(dir.path); + const container = this._findContainer(dir.path); if (isPresent(container)) { container.removeControl(dir.name); } @@ -111,8 +112,8 @@ export class NgForm extends ControlContainer implements Form { addFormGroup(dir: NgModelGroup): void { resolvedPromise.then(() => { - var container = this._findContainer(dir.path); - var group = new FormGroup({}); + const container = this._findContainer(dir.path); + const group = new FormGroup({}); setUpFormContainer(group, dir); container.registerControl(dir.name, group); group.updateValueAndValidity({emitEvent: false}); @@ -121,7 +122,7 @@ export class NgForm extends ControlContainer implements Form { removeFormGroup(dir: NgModelGroup): void { resolvedPromise.then(() => { - var container = this._findContainer(dir.path); + const container = this._findContainer(dir.path); if (isPresent(container)) { container.removeControl(dir.name); } @@ -132,16 +133,16 @@ export class NgForm extends ControlContainer implements Form { updateModel(dir: NgControl, value: any): void { resolvedPromise.then(() => { - var ctrl = this.form.get(dir.path); + const ctrl = this.form.get(dir.path); ctrl.setValue(value); }); } setValue(value: {[key: string]: any}): void { this.control.setValue(value); } - onSubmit(): boolean { + onSubmit($event: Event): boolean { this._submitted = true; - this.ngSubmit.emit(null); + this.ngSubmit.emit($event); return false; } diff --git a/modules/@angular/forms/src/directives/reactive_directives/form_group_directive.ts b/modules/@angular/forms/src/directives/reactive_directives/form_group_directive.ts index d908ababc8..8ede88932c 100644 --- a/modules/@angular/forms/src/directives/reactive_directives/form_group_directive.ts +++ b/modules/@angular/forms/src/directives/reactive_directives/form_group_directive.ts @@ -44,6 +44,10 @@ export const formDirectiveProvider: any = { * its {@link AbstractControl.statusChanges} event to be notified when the validation status is * re-calculated. * + * Furthermore, you can listen to the directive's `ngSubmit` event to be notified when the user has + * triggered a form submission. The `ngSubmit` event will be emitted with the original form + * submission event. + * * ### Example * * In this example, we create form controls for first name and last name. @@ -59,7 +63,7 @@ export const formDirectiveProvider: any = { @Directive({ selector: '[formGroup]', providers: [formDirectiveProvider], - host: {'(submit)': 'onSubmit()', '(reset)': 'onReset()'}, + host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'}, exportAs: 'ngForm' }) export class FormGroupDirective extends ControlContainer implements Form, @@ -107,7 +111,7 @@ export class FormGroupDirective extends ControlContainer implements Form, removeControl(dir: FormControlName): void { ListWrapper.remove(this.directives, dir); } addFormGroup(dir: FormGroupName): void { - var ctrl: any = this.form.get(dir.path); + const ctrl: any = this.form.get(dir.path); setUpFormContainer(ctrl, dir); ctrl.updateValueAndValidity({emitEvent: false}); } @@ -117,7 +121,7 @@ export class FormGroupDirective extends ControlContainer implements Form, getFormGroup(dir: FormGroupName): FormGroup { return this.form.get(dir.path); } addFormArray(dir: FormArrayName): void { - var ctrl: any = this.form.get(dir.path); + const ctrl: any = this.form.get(dir.path); setUpFormContainer(ctrl, dir); ctrl.updateValueAndValidity({emitEvent: false}); } @@ -127,13 +131,13 @@ export class FormGroupDirective extends ControlContainer implements Form, getFormArray(dir: FormArrayName): FormArray { return this.form.get(dir.path); } updateModel(dir: FormControlName, value: any): void { - var ctrl  = this.form.get(dir.path); + const ctrl  = this.form.get(dir.path); ctrl.setValue(value); } - onSubmit(): boolean { + onSubmit($event: Event): boolean { this._submitted = true; - this.ngSubmit.emit(null); + this.ngSubmit.emit($event); return false; } diff --git a/modules/@angular/forms/test/reactive_integration_spec.ts b/modules/@angular/forms/test/reactive_integration_spec.ts index d4763e0f39..3e63ac92af 100644 --- a/modules/@angular/forms/test/reactive_integration_spec.ts +++ b/modules/@angular/forms/test/reactive_integration_spec.ts @@ -529,17 +529,17 @@ export function main() { }); describe('submit and reset events', () => { - it('should emit ngSubmit event on submit', () => { + it('should emit ngSubmit event with the original submit event on submit', () => { const fixture = TestBed.createComponent(FormGroupComp); fixture.componentInstance.form = new FormGroup({'login': new FormControl('loginValue')}); - fixture.componentInstance.data = 'should be changed'; + fixture.componentInstance.event = null; fixture.detectChanges(); const formEl = fixture.debugElement.query(By.css('form')).nativeElement; dispatchEvent(formEl, 'submit'); fixture.detectChanges(); - expect(fixture.componentInstance.data).toEqual('submitted'); + expect(fixture.componentInstance.event.type).toEqual('submit'); }); it('should mark formGroup as submitted on submit event', () => { @@ -1760,7 +1760,7 @@ class FormControlComp { @Component({ selector: 'form-group-comp', template: ` -
+
` @@ -1769,7 +1769,7 @@ class FormGroupComp { control: FormControl; form: FormGroup; myGroup: FormGroup; - data: string; + event: Event; } @Component({ diff --git a/modules/@angular/forms/test/template_integration_spec.ts b/modules/@angular/forms/test/template_integration_spec.ts index 7d5a20cffd..a71802258d 100644 --- a/modules/@angular/forms/test/template_integration_spec.ts +++ b/modules/@angular/forms/test/template_integration_spec.ts @@ -237,15 +237,15 @@ export function main() { }); describe('submit and reset events', () => { - it('should emit ngSubmit event on submit', fakeAsync(() => { + it('should emit ngSubmit event with the original submit event on submit', fakeAsync(() => { const fixture = TestBed.createComponent(NgModelForm); - fixture.componentInstance.name = 'old'; + fixture.componentInstance.event = null; const form = fixture.debugElement.query(By.css('form')); dispatchEvent(form.nativeElement, 'submit'); tick(); - expect(fixture.componentInstance.name).toEqual('submitted'); + expect(fixture.componentInstance.event.type).toEqual('submit'); })); it('should mark NgForm as submitted on submit event', fakeAsync(() => { @@ -898,13 +898,14 @@ class StandaloneNgModel { @Component({ selector: 'ng-model-form', template: ` -
+
` }) class NgModelForm { name: string; + event: Event; options = {}; onReset() {} diff --git a/tools/public_api_guard/forms/index.d.ts b/tools/public_api_guard/forms/index.d.ts index ca108f8610..95bd3d06a0 100644 --- a/tools/public_api_guard/forms/index.d.ts +++ b/tools/public_api_guard/forms/index.d.ts @@ -299,7 +299,7 @@ export declare class FormGroupDirective extends ControlContainer implements Form getFormGroup(dir: FormGroupName): FormGroup; ngOnChanges(changes: SimpleChanges): void; onReset(): void; - onSubmit(): boolean; + onSubmit($event: Event): boolean; removeControl(dir: FormControlName): void; removeFormArray(dir: FormArrayName): void; removeFormGroup(dir: FormGroupName): void; @@ -382,7 +382,7 @@ export declare class NgForm extends ControlContainer implements Form { getControl(dir: NgModel): FormControl; getFormGroup(dir: NgModelGroup): FormGroup; onReset(): void; - onSubmit(): boolean; + onSubmit($event: Event): boolean; removeControl(dir: NgModel): void; removeFormGroup(dir: NgModelGroup): void; resetForm(value?: any): void;