Skip to content

Commit 56b9591

Browse files
Kevin Fahymhevery
authored andcommitted
fix(forms): prevent event emission on enable/disable when emitEvent is false (#12366) (#21018)
Previously, the emitEvent flag was only checked when emitting on the current control. Thus, if the control was part of a hierarchy, events were emitted on the parent and the childrens. This fixes the issue by properly passing the emitEvent flag to both parent and childrens. Fixes #12366 PR Close #21018
1 parent b0ddb5a commit 56b9591

File tree

4 files changed

+73
-7
lines changed

4 files changed

+73
-7
lines changed

packages/forms/src/model.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -352,15 +352,16 @@ export abstract class AbstractControl {
352352
disable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {
353353
(this as{status: string}).status = DISABLED;
354354
(this as{errors: ValidationErrors | null}).errors = null;
355-
this._forEachChild((control: AbstractControl) => { control.disable({onlySelf: true}); });
355+
this._forEachChild(
356+
(control: AbstractControl) => { control.disable({...opts, onlySelf: true}); });
356357
this._updateValue();
357358

358359
if (opts.emitEvent !== false) {
359360
(this.valueChanges as EventEmitter<any>).emit(this.value);
360361
(this.statusChanges as EventEmitter<string>).emit(this.status);
361362
}
362363

363-
this._updateAncestors(!!opts.onlySelf);
364+
this._updateAncestors(opts);
364365
this._onDisabledChange.forEach((changeFn) => changeFn(true));
365366
}
366367

@@ -373,16 +374,17 @@ export abstract class AbstractControl {
373374
*/
374375
enable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {
375376
(this as{status: string}).status = VALID;
376-
this._forEachChild((control: AbstractControl) => { control.enable({onlySelf: true}); });
377+
this._forEachChild(
378+
(control: AbstractControl) => { control.enable({...opts, onlySelf: true}); });
377379
this.updateValueAndValidity({onlySelf: true, emitEvent: opts.emitEvent});
378380

379-
this._updateAncestors(!!opts.onlySelf);
381+
this._updateAncestors(opts);
380382
this._onDisabledChange.forEach((changeFn) => changeFn(false));
381383
}
382384

383-
private _updateAncestors(onlySelf: boolean) {
384-
if (this._parent && !onlySelf) {
385-
this._parent.updateValueAndValidity();
385+
private _updateAncestors(opts: {onlySelf?: boolean, emitEvent?: boolean}) {
386+
if (this._parent && !opts.onlySelf) {
387+
this._parent.updateValueAndValidity(opts);
386388
this._parent._updatePristine();
387389
this._parent._updateTouched();
388390
}

packages/forms/test/form_array_spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,28 @@ import {of } from 'rxjs/observable/of';
10531053
expect(logger).toEqual(['control', 'array', 'form']);
10541054
});
10551055

1056+
it('should not emit value change events when emitEvent = false', () => {
1057+
c.valueChanges.subscribe(() => logger.push('control'));
1058+
a.valueChanges.subscribe(() => logger.push('array'));
1059+
form.valueChanges.subscribe(() => logger.push('form'));
1060+
1061+
a.disable({emitEvent: false});
1062+
expect(logger).toEqual([]);
1063+
a.enable({emitEvent: false});
1064+
expect(logger).toEqual([]);
1065+
});
1066+
1067+
it('should not emit status change events when emitEvent = false', () => {
1068+
c.statusChanges.subscribe(() => logger.push('control'));
1069+
a.statusChanges.subscribe(() => logger.push('array'));
1070+
form.statusChanges.subscribe(() => logger.push('form'));
1071+
1072+
a.disable({emitEvent: false});
1073+
expect(logger).toEqual([]);
1074+
a.enable({emitEvent: false});
1075+
expect(logger).toEqual([]);
1076+
});
1077+
10561078
});
10571079

10581080
describe('setControl()', () => {

packages/forms/test/form_control_spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,6 +1139,26 @@ import {FormArray} from '@angular/forms/src/model';
11391139
expect(fn).toThrowError(`Expected validator to return Promise or Observable.`);
11401140
});
11411141

1142+
it('should not emit value change events when emitEvent = false', () => {
1143+
c.valueChanges.subscribe(() => logger.push('control'));
1144+
g.valueChanges.subscribe(() => logger.push('group'));
1145+
1146+
c.disable({emitEvent: false});
1147+
expect(logger).toEqual([]);
1148+
c.enable({emitEvent: false});
1149+
expect(logger).toEqual([]);
1150+
});
1151+
1152+
it('should not emit status change events when emitEvent = false', () => {
1153+
c.statusChanges.subscribe(() => logger.push('control'));
1154+
g.statusChanges.subscribe(() => logger.push('form'));
1155+
1156+
c.disable({emitEvent: false});
1157+
expect(logger).toEqual([]);
1158+
c.enable({emitEvent: false});
1159+
expect(logger).toEqual([]);
1160+
});
1161+
11421162
});
11431163
});
11441164
});

packages/forms/test/form_group_spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,28 @@ import {of } from 'rxjs/observable/of';
10451045
expect(logger).toEqual(['control', 'group', 'form']);
10461046
});
10471047

1048+
it('should not emit value change events when emitEvent = false', () => {
1049+
c.valueChanges.subscribe(() => logger.push('control'));
1050+
g.valueChanges.subscribe(() => logger.push('group'));
1051+
form.valueChanges.subscribe(() => logger.push('form'));
1052+
1053+
g.disable({emitEvent: false});
1054+
expect(logger).toEqual([]);
1055+
g.enable({emitEvent: false});
1056+
expect(logger).toEqual([]);
1057+
});
1058+
1059+
it('should not emit status change events when emitEvent = false', () => {
1060+
c.statusChanges.subscribe(() => logger.push('control'));
1061+
g.statusChanges.subscribe(() => logger.push('group'));
1062+
form.statusChanges.subscribe(() => logger.push('form'));
1063+
1064+
g.disable({emitEvent: false});
1065+
expect(logger).toEqual([]);
1066+
g.enable({emitEvent: false});
1067+
expect(logger).toEqual([]);
1068+
});
1069+
10481070
});
10491071

10501072
});

0 commit comments

Comments
 (0)