From 08a40ba87072923693543daf71efd7008426ebc8 Mon Sep 17 00:00:00 2001 From: anna-zhernovkova Date: Tue, 20 Mar 2018 18:12:48 +0300 Subject: [PATCH] Prevent option change event firing when changes occur in component (#712) (#717) * Prevent option change event firing when changes occur in component * Update event lockers * Fix typo * Add test for bound options * Simplify lockers * Refactor test * Prevent option change event firing when nested option was changed * Move event locker to writeValue method * Rework test * Fix typo --- src/core/events-strategy.ts | 4 ++++ templates/component.tst | 2 ++ ...stom-value-accessor-implementation.spec.ts | 21 +++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/src/core/events-strategy.ts b/src/core/events-strategy.ts index e557be18e..d2050c062 100644 --- a/src/core/events-strategy.ts +++ b/src/core/events-strategy.ts @@ -93,12 +93,16 @@ let createOnStableSubscription = function(ngZone: NgZone, fireNgEvent: Function) export class EmitterHelper { strategy: NgEventsStrategy; + lockedValueChangeEvent = false; constructor(ngZone: NgZone, public component: DxComponent) { this.strategy = new NgEventsStrategy(component, ngZone); createOnStableSubscription(ngZone, this.fireNgEvent); } fireNgEvent(eventName: string, eventArgs: any) { + if (this.lockedValueChangeEvent && eventName === 'valueChange') { + return; + } let emitter = this.component[eventName]; if (emitter) { emitter.next(eventArgs && eventArgs[0]); diff --git a/templates/component.tst b/templates/component.tst index 82c2b660b..11702bb25 100644 --- a/templates/component.tst +++ b/templates/component.tst @@ -139,7 +139,9 @@ export class <#= it.className #>Component extends <#= baseClass #> <#? implement } <#? it.isEditor #> writeValue(value: any): void { + this.eventHelper.lockedValueChangeEvent = true; this.value = value; + this.eventHelper.lockedValueChangeEvent = false; } <#? it.widgetName !== "dxRangeSelector" #> setDisabledState(isDisabled: boolean): void { diff --git a/tests/src/ui/custom-value-accessor-implementation.spec.ts b/tests/src/ui/custom-value-accessor-implementation.spec.ts index b02981ee5..ad9bfd8f0 100644 --- a/tests/src/ui/custom-value-accessor-implementation.spec.ts +++ b/tests/src/ui/custom-value-accessor-implementation.spec.ts @@ -78,6 +78,7 @@ describe('DxTextBox value accessor', () => { expect(instance.option('disabled')).toBe(false); })); + it('should change the value', async(() => { let fixture = TestBed.createComponent(TestContainerComponent); fixture.detectChanges(); @@ -89,6 +90,7 @@ describe('DxTextBox value accessor', () => { expect(instance.option('value')).toBe('text'); })); + it('should change touched option', async(() => { let fixture = TestBed.createComponent(TestContainerComponent); fixture.detectChanges(); @@ -102,4 +104,23 @@ describe('DxTextBox value accessor', () => { expect(fixture.componentInstance.formControl.touched).toBe(true); })); + + it('should not fire valueChanges event when patchValue method is used with emitEvent=false (T614207)', () => { + let fixture = TestBed.createComponent(TestContainerComponent); + fixture.detectChanges(); + + let component = fixture.componentInstance, + form = component.form, + testSpy = jasmine.createSpy('testSpy'); + + form.valueChanges.subscribe(testSpy); + + form.controls['formControl'].patchValue('text', { emitEvent: false }); + fixture.detectChanges(); + expect(testSpy).toHaveBeenCalledTimes(0); + + form.controls['formControl'].patchValue('text2'); + fixture.detectChanges(); + expect(testSpy).toHaveBeenCalledTimes(1); + }); });