diff --git a/src/lib/slider/slider.spec.ts b/src/lib/slider/slider.spec.ts index 72f7851e3593..b53a6be2408a 100644 --- a/src/lib/slider/slider.spec.ts +++ b/src/lib/slider/slider.spec.ts @@ -490,6 +490,17 @@ describe('MatSlider', () => { expect(sliderInstance.value).toBe(33.3); }); + it('should truncate long decimal values when using a decimal step and the arrow keys', () => { + fixture.componentInstance.step = 0.1; + fixture.detectChanges(); + + for (let i = 0; i < 3; i++) { + dispatchKeyboardEvent(sliderNativeElement, 'keydown', UP_ARROW); + } + + expect(sliderInstance.value).toBe(0.3); + }); + }); describe('slider with auto ticks', () => { diff --git a/src/lib/slider/slider.ts b/src/lib/slider/slider.ts index 7a5a9ef17893..49b3f001e35e 100644 --- a/src/lib/slider/slider.ts +++ b/src/lib/slider/slider.ts @@ -224,7 +224,15 @@ export class MatSlider extends _MatSliderMixinBase } set value(v: number | null) { if (v !== this._value) { - this._value = coerceNumberProperty(v); + let value = coerceNumberProperty(v); + + // While incrementing by a decimal we can end up with values like 33.300000000000004. + // Truncate it to ensure that it matches the label and to make it easier to work with. + if (this._roundToDecimal) { + value = parseFloat(value.toFixed(this._roundToDecimal)); + } + + this._value = value; this._percent = this._calculatePercentage(this._value); // Since this also modifies the percentage, we need to let the change detection know. @@ -638,17 +646,11 @@ export class MatSlider extends _MatSliderMixinBase } else if (percent === 1) { this.value = this.max; } else { - let exactValue = this._calculateValue(percent); + const exactValue = this._calculateValue(percent); // This calculation finds the closest step by finding the closest // whole number divisible by the step relative to the min. - let closestValue = Math.round((exactValue - this.min) / this.step) * this.step + this.min; - - // If we've got a step with a decimal, we may end up with something like 33.300000000000004. - // Truncate the value to ensure that it matches the label and to make it easier to work with. - if (this._roundToDecimal) { - closestValue = parseFloat(closestValue.toFixed(this._roundToDecimal)); - } + const closestValue = Math.round((exactValue - this.min) / this.step) * this.step + this.min; // The value needs to snap to the min and max. this.value = this._clamp(closestValue, this.min, this.max);