diff --git a/angular/src/directives/control-value-accessors/boolean-value-accessor.ts b/angular/src/directives/control-value-accessors/boolean-value-accessor.ts index 1725f6dd2a..f9e0cf2248 100644 --- a/angular/src/directives/control-value-accessors/boolean-value-accessor.ts +++ b/angular/src/directives/control-value-accessors/boolean-value-accessor.ts @@ -24,14 +24,25 @@ export class BooleanValueAccessor implements ControlValueAccessor { onChange: (value: any) => void; onTouched: () => void; + /** + * Whether onChange should be mutted (not be fired). Will be true only when writeValue was called, which + * means that value changed inside angular form (e.g. calling setValue on a control). + */ + private muteOnChange = false; + writeValue(value: any) { + this.muteOnChange = true; this.element.nativeElement.checked = value; setIonicClasses(this.element); } @HostListener('ionChange', ['$event.target.checked']) _handleIonChange(value: any) { - this.onChange(value); + if (!this.muteOnChange) { + this.onChange(value); + } + + this.muteOnChange = false; requestAnimationFrame(() => { setIonicClasses(this.element); diff --git a/angular/src/directives/control-value-accessors/numeric-value-accesssor.ts b/angular/src/directives/control-value-accessors/numeric-value-accesssor.ts index fdf42d3b08..416d784381 100644 --- a/angular/src/directives/control-value-accessors/numeric-value-accesssor.ts +++ b/angular/src/directives/control-value-accessors/numeric-value-accesssor.ts @@ -24,7 +24,15 @@ export class NumericValueAccessor implements ControlValueAccessor { onChange: (value: any) => void; onTouched: () => void; + /** + * Whether onChange should be mutted (not be fired). Will be true only when writeValue was called, which + * means that value changed inside angular form (e.g. calling setValue on a control). + */ + private muteOnChange = false; + writeValue(value: any) { + this.muteOnChange = true; + // The value needs to be normalized for IE9, otherwise it is set to 'null' when null // Probably not an issue for us, but it doesn't really cost anything either this.element.nativeElement.value = value == null ? '' : value; @@ -33,7 +41,11 @@ export class NumericValueAccessor implements ControlValueAccessor { @HostListener('ionChange', ['$event.target.value']) _handleInputEvent(value: any) { - this.onChange(value); + if (!this.muteOnChange) { + this.onChange(value); + } + + this.muteOnChange = false; requestAnimationFrame(() => { setIonicClasses(this.element); diff --git a/angular/src/directives/control-value-accessors/radio-value-accessor.ts b/angular/src/directives/control-value-accessors/radio-value-accessor.ts index b4d1266797..e460a53104 100644 --- a/angular/src/directives/control-value-accessors/radio-value-accessor.ts +++ b/angular/src/directives/control-value-accessors/radio-value-accessor.ts @@ -25,7 +25,14 @@ export class RadioValueAccessor implements ControlValueAccessor { this.onTouched = () => {/**/}; } + /** + * Whether onChange should be mutted (not be fired). Will be true only when writeValue was called, which + * means that value changed inside angular form (e.g. calling setValue on a control). + */ + private muteOnChange = false; + writeValue(value: any) { + this.muteOnChange = true; this.element.nativeElement.checked = this.value = value; requestAnimationFrame(() => { @@ -35,7 +42,11 @@ export class RadioValueAccessor implements ControlValueAccessor { @HostListener('ionSelect', ['$event.target.checked']) _handleIonSelect(value: any) { - this.onChange(value); + if (!this.muteOnChange) { + this.onChange(value); + } + + this.muteOnChange = false; requestAnimationFrame(() => { setIonicClasses(this.element); diff --git a/angular/src/directives/control-value-accessors/select-value-accessor.ts b/angular/src/directives/control-value-accessors/select-value-accessor.ts index 7bffa1b0bf..30367481af 100644 --- a/angular/src/directives/control-value-accessors/select-value-accessor.ts +++ b/angular/src/directives/control-value-accessors/select-value-accessor.ts @@ -24,7 +24,14 @@ export class SelectValueAccessor implements ControlValueAccessor { onChange: (value: any) => void; onTouched: () => void; + /** + * Whether onChange should be mutted (not be fired). Will be true only when writeValue was called, which + * means that value changed inside angular form (e.g. calling setValue on a control). + */ + private muteOnChange = false; + writeValue(value: any) { + this.muteOnChange = true; this.element.nativeElement.value = value; requestAnimationFrame(() => { @@ -34,7 +41,11 @@ export class SelectValueAccessor implements ControlValueAccessor { @HostListener('ionChange', ['$event.target.value']) _handleChangeEvent(value: any) { - this.onChange(value); + if (!this.muteOnChange) { + this.onChange(value); + } + + this.muteOnChange = false; requestAnimationFrame(() => { setIonicClasses(this.element); diff --git a/angular/src/directives/control-value-accessors/text-value-accessor.ts b/angular/src/directives/control-value-accessors/text-value-accessor.ts index 8db0441f38..8547611345 100644 --- a/angular/src/directives/control-value-accessors/text-value-accessor.ts +++ b/angular/src/directives/control-value-accessors/text-value-accessor.ts @@ -24,7 +24,14 @@ export class TextValueAccessor implements ControlValueAccessor { onChange: (value: any) => void; onTouched: () => void; + /** + * Whether onChange should be mutted (not be fired). Will be true only when writeValue was called, which + * means that value changed inside angular form (e.g. calling setValue on a control). + */ + private muteOnChange = false; + writeValue(value: any) { + this.muteOnChange = true; this.element.nativeElement.value = value; requestAnimationFrame(() => { @@ -34,7 +41,11 @@ export class TextValueAccessor implements ControlValueAccessor { @HostListener('ionChange', ['$event.target.value']) _handleInputEvent(value: any) { - this.onChange(value); + if (!this.muteOnChange) { + this.onChange(value); + } + + this.muteOnChange = false; requestAnimationFrame(() => { setIonicClasses(this.element);