diff --git a/src/core/events-strategy.ts b/src/core/events-strategy.ts index 23e7d89a1..d891406fc 100644 --- a/src/core/events-strategy.ts +++ b/src/core/events-strategy.ts @@ -67,11 +67,15 @@ export class NgEventsStrategy { export class EmitterHelper { strategy: NgEventsStrategy; + lockedValueChangeEvent = false; constructor(ngZone: NgZone, public component: DxComponent) { this.strategy = new NgEventsStrategy(component, ngZone); } 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 2d08882fd..b836e8f48 100644 --- a/templates/component.tst +++ b/templates/component.tst @@ -147,7 +147,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); + }); });