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
This commit is contained in:
parent
5effc330ed
commit
17e3410d98
|
@ -48,7 +48,8 @@ const resolvedPromise = Promise.resolve(null);
|
||||||
* sub-groups within the form.
|
* sub-groups within the form.
|
||||||
*
|
*
|
||||||
* You can listen to the directive's `ngSubmit` event to be notified when the user has
|
* 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'}
|
* {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}
|
||||||
*
|
*
|
||||||
|
@ -61,7 +62,7 @@ const resolvedPromise = Promise.resolve(null);
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'form:not([ngNoForm]):not([formGroup]),ngForm,[ngForm]',
|
selector: 'form:not([ngNoForm]):not([formGroup]),ngForm,[ngForm]',
|
||||||
providers: [formDirectiveProvider],
|
providers: [formDirectiveProvider],
|
||||||
host: {'(submit)': 'onSubmit()', '(reset)': 'onReset()'},
|
host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'},
|
||||||
outputs: ['ngSubmit'],
|
outputs: ['ngSubmit'],
|
||||||
exportAs: 'ngForm'
|
exportAs: 'ngForm'
|
||||||
})
|
})
|
||||||
|
@ -102,7 +103,7 @@ export class NgForm extends ControlContainer implements Form {
|
||||||
|
|
||||||
removeControl(dir: NgModel): void {
|
removeControl(dir: NgModel): void {
|
||||||
resolvedPromise.then(() => {
|
resolvedPromise.then(() => {
|
||||||
var container = this._findContainer(dir.path);
|
const container = this._findContainer(dir.path);
|
||||||
if (isPresent(container)) {
|
if (isPresent(container)) {
|
||||||
container.removeControl(dir.name);
|
container.removeControl(dir.name);
|
||||||
}
|
}
|
||||||
|
@ -111,8 +112,8 @@ export class NgForm extends ControlContainer implements Form {
|
||||||
|
|
||||||
addFormGroup(dir: NgModelGroup): void {
|
addFormGroup(dir: NgModelGroup): void {
|
||||||
resolvedPromise.then(() => {
|
resolvedPromise.then(() => {
|
||||||
var container = this._findContainer(dir.path);
|
const container = this._findContainer(dir.path);
|
||||||
var group = new FormGroup({});
|
const group = new FormGroup({});
|
||||||
setUpFormContainer(group, dir);
|
setUpFormContainer(group, dir);
|
||||||
container.registerControl(dir.name, group);
|
container.registerControl(dir.name, group);
|
||||||
group.updateValueAndValidity({emitEvent: false});
|
group.updateValueAndValidity({emitEvent: false});
|
||||||
|
@ -121,7 +122,7 @@ export class NgForm extends ControlContainer implements Form {
|
||||||
|
|
||||||
removeFormGroup(dir: NgModelGroup): void {
|
removeFormGroup(dir: NgModelGroup): void {
|
||||||
resolvedPromise.then(() => {
|
resolvedPromise.then(() => {
|
||||||
var container = this._findContainer(dir.path);
|
const container = this._findContainer(dir.path);
|
||||||
if (isPresent(container)) {
|
if (isPresent(container)) {
|
||||||
container.removeControl(dir.name);
|
container.removeControl(dir.name);
|
||||||
}
|
}
|
||||||
|
@ -132,16 +133,16 @@ export class NgForm extends ControlContainer implements Form {
|
||||||
|
|
||||||
updateModel(dir: NgControl, value: any): void {
|
updateModel(dir: NgControl, value: any): void {
|
||||||
resolvedPromise.then(() => {
|
resolvedPromise.then(() => {
|
||||||
var ctrl = <FormControl>this.form.get(dir.path);
|
const ctrl = <FormControl>this.form.get(dir.path);
|
||||||
ctrl.setValue(value);
|
ctrl.setValue(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(value: {[key: string]: any}): void { this.control.setValue(value); }
|
setValue(value: {[key: string]: any}): void { this.control.setValue(value); }
|
||||||
|
|
||||||
onSubmit(): boolean {
|
onSubmit($event: Event): boolean {
|
||||||
this._submitted = true;
|
this._submitted = true;
|
||||||
this.ngSubmit.emit(null);
|
this.ngSubmit.emit($event);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,10 @@ export const formDirectiveProvider: any = {
|
||||||
* its {@link AbstractControl.statusChanges} event to be notified when the validation status is
|
* its {@link AbstractControl.statusChanges} event to be notified when the validation status is
|
||||||
* re-calculated.
|
* 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
|
* ### Example
|
||||||
*
|
*
|
||||||
* In this example, we create form controls for first name and last name.
|
* In this example, we create form controls for first name and last name.
|
||||||
|
@ -59,7 +63,7 @@ export const formDirectiveProvider: any = {
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[formGroup]',
|
selector: '[formGroup]',
|
||||||
providers: [formDirectiveProvider],
|
providers: [formDirectiveProvider],
|
||||||
host: {'(submit)': 'onSubmit()', '(reset)': 'onReset()'},
|
host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'},
|
||||||
exportAs: 'ngForm'
|
exportAs: 'ngForm'
|
||||||
})
|
})
|
||||||
export class FormGroupDirective extends ControlContainer implements Form,
|
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); }
|
removeControl(dir: FormControlName): void { ListWrapper.remove(this.directives, dir); }
|
||||||
|
|
||||||
addFormGroup(dir: FormGroupName): void {
|
addFormGroup(dir: FormGroupName): void {
|
||||||
var ctrl: any = this.form.get(dir.path);
|
const ctrl: any = this.form.get(dir.path);
|
||||||
setUpFormContainer(ctrl, dir);
|
setUpFormContainer(ctrl, dir);
|
||||||
ctrl.updateValueAndValidity({emitEvent: false});
|
ctrl.updateValueAndValidity({emitEvent: false});
|
||||||
}
|
}
|
||||||
|
@ -117,7 +121,7 @@ export class FormGroupDirective extends ControlContainer implements Form,
|
||||||
getFormGroup(dir: FormGroupName): FormGroup { return <FormGroup>this.form.get(dir.path); }
|
getFormGroup(dir: FormGroupName): FormGroup { return <FormGroup>this.form.get(dir.path); }
|
||||||
|
|
||||||
addFormArray(dir: FormArrayName): void {
|
addFormArray(dir: FormArrayName): void {
|
||||||
var ctrl: any = this.form.get(dir.path);
|
const ctrl: any = this.form.get(dir.path);
|
||||||
setUpFormContainer(ctrl, dir);
|
setUpFormContainer(ctrl, dir);
|
||||||
ctrl.updateValueAndValidity({emitEvent: false});
|
ctrl.updateValueAndValidity({emitEvent: false});
|
||||||
}
|
}
|
||||||
|
@ -127,13 +131,13 @@ export class FormGroupDirective extends ControlContainer implements Form,
|
||||||
getFormArray(dir: FormArrayName): FormArray { return <FormArray>this.form.get(dir.path); }
|
getFormArray(dir: FormArrayName): FormArray { return <FormArray>this.form.get(dir.path); }
|
||||||
|
|
||||||
updateModel(dir: FormControlName, value: any): void {
|
updateModel(dir: FormControlName, value: any): void {
|
||||||
var ctrl = <FormControl>this.form.get(dir.path);
|
const ctrl = <FormControl>this.form.get(dir.path);
|
||||||
ctrl.setValue(value);
|
ctrl.setValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit(): boolean {
|
onSubmit($event: Event): boolean {
|
||||||
this._submitted = true;
|
this._submitted = true;
|
||||||
this.ngSubmit.emit(null);
|
this.ngSubmit.emit($event);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -529,17 +529,17 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('submit and reset events', () => {
|
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);
|
const fixture = TestBed.createComponent(FormGroupComp);
|
||||||
fixture.componentInstance.form = new FormGroup({'login': new FormControl('loginValue')});
|
fixture.componentInstance.form = new FormGroup({'login': new FormControl('loginValue')});
|
||||||
fixture.componentInstance.data = 'should be changed';
|
fixture.componentInstance.event = null;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
|
const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
|
||||||
dispatchEvent(formEl, 'submit');
|
dispatchEvent(formEl, 'submit');
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(fixture.componentInstance.data).toEqual('submitted');
|
expect(fixture.componentInstance.event.type).toEqual('submit');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should mark formGroup as submitted on submit event', () => {
|
it('should mark formGroup as submitted on submit event', () => {
|
||||||
|
@ -1760,7 +1760,7 @@ class FormControlComp {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'form-group-comp',
|
selector: 'form-group-comp',
|
||||||
template: `
|
template: `
|
||||||
<form [formGroup]="form" (ngSubmit)="data='submitted'">
|
<form [formGroup]="form" (ngSubmit)="event=$event">
|
||||||
<input type="text" formControlName="login">
|
<input type="text" formControlName="login">
|
||||||
</form>
|
</form>
|
||||||
`
|
`
|
||||||
|
@ -1769,7 +1769,7 @@ class FormGroupComp {
|
||||||
control: FormControl;
|
control: FormControl;
|
||||||
form: FormGroup;
|
form: FormGroup;
|
||||||
myGroup: FormGroup;
|
myGroup: FormGroup;
|
||||||
data: string;
|
event: Event;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
|
@ -237,15 +237,15 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('submit and reset events', () => {
|
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);
|
const fixture = TestBed.createComponent(NgModelForm);
|
||||||
fixture.componentInstance.name = 'old';
|
fixture.componentInstance.event = null;
|
||||||
|
|
||||||
const form = fixture.debugElement.query(By.css('form'));
|
const form = fixture.debugElement.query(By.css('form'));
|
||||||
dispatchEvent(form.nativeElement, 'submit');
|
dispatchEvent(form.nativeElement, 'submit');
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
expect(fixture.componentInstance.name).toEqual('submitted');
|
expect(fixture.componentInstance.event.type).toEqual('submit');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should mark NgForm as submitted on submit event', fakeAsync(() => {
|
it('should mark NgForm as submitted on submit event', fakeAsync(() => {
|
||||||
|
@ -898,13 +898,14 @@ class StandaloneNgModel {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ng-model-form',
|
selector: 'ng-model-form',
|
||||||
template: `
|
template: `
|
||||||
<form (ngSubmit)="name='submitted'" (reset)="onReset()">
|
<form (ngSubmit)="event=$event" (reset)="onReset()">
|
||||||
<input name="name" [(ngModel)]="name" minlength="10" [ngModelOptions]="options">
|
<input name="name" [(ngModel)]="name" minlength="10" [ngModelOptions]="options">
|
||||||
</form>
|
</form>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
class NgModelForm {
|
class NgModelForm {
|
||||||
name: string;
|
name: string;
|
||||||
|
event: Event;
|
||||||
options = {};
|
options = {};
|
||||||
|
|
||||||
onReset() {}
|
onReset() {}
|
||||||
|
|
|
@ -299,7 +299,7 @@ export declare class FormGroupDirective extends ControlContainer implements Form
|
||||||
getFormGroup(dir: FormGroupName): FormGroup;
|
getFormGroup(dir: FormGroupName): FormGroup;
|
||||||
ngOnChanges(changes: SimpleChanges): void;
|
ngOnChanges(changes: SimpleChanges): void;
|
||||||
onReset(): void;
|
onReset(): void;
|
||||||
onSubmit(): boolean;
|
onSubmit($event: Event): boolean;
|
||||||
removeControl(dir: FormControlName): void;
|
removeControl(dir: FormControlName): void;
|
||||||
removeFormArray(dir: FormArrayName): void;
|
removeFormArray(dir: FormArrayName): void;
|
||||||
removeFormGroup(dir: FormGroupName): void;
|
removeFormGroup(dir: FormGroupName): void;
|
||||||
|
@ -382,7 +382,7 @@ export declare class NgForm extends ControlContainer implements Form {
|
||||||
getControl(dir: NgModel): FormControl;
|
getControl(dir: NgModel): FormControl;
|
||||||
getFormGroup(dir: NgModelGroup): FormGroup;
|
getFormGroup(dir: NgModelGroup): FormGroup;
|
||||||
onReset(): void;
|
onReset(): void;
|
||||||
onSubmit(): boolean;
|
onSubmit($event: Event): boolean;
|
||||||
removeControl(dir: NgModel): void;
|
removeControl(dir: NgModel): void;
|
||||||
removeFormGroup(dir: NgModelGroup): void;
|
removeFormGroup(dir: NgModelGroup): void;
|
||||||
resetForm(value?: any): void;
|
resetForm(value?: any): void;
|
||||||
|
|
Loading…
Reference in New Issue