Skip to content

Commit 61f0f2a

Browse files
crisbetoandrewseguin
authored andcommitted
fix(slider): value not being rounded when using keyboard and decimal step (#11574)
When incrementing a slider using the keyboard, the value can end up looking like 33.300000000000004, if the consumer set a decimal step. We fixed this a while ago for dragging, but that didn't cover the keyboard interactions. These changes move the logic from the earlier fix so it can apply everywhere. Relates to #10951.
1 parent 555d8f4 commit 61f0f2a

File tree

2 files changed

+22
-9
lines changed

2 files changed

+22
-9
lines changed

src/lib/slider/slider.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,17 @@ describe('MatSlider', () => {
490490
expect(sliderInstance.value).toBe(33.3);
491491
});
492492

493+
it('should truncate long decimal values when using a decimal step and the arrow keys', () => {
494+
fixture.componentInstance.step = 0.1;
495+
fixture.detectChanges();
496+
497+
for (let i = 0; i < 3; i++) {
498+
dispatchKeyboardEvent(sliderNativeElement, 'keydown', UP_ARROW);
499+
}
500+
501+
expect(sliderInstance.value).toBe(0.3);
502+
});
503+
493504
});
494505

495506
describe('slider with auto ticks', () => {

src/lib/slider/slider.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,15 @@ export class MatSlider extends _MatSliderMixinBase
224224
}
225225
set value(v: number | null) {
226226
if (v !== this._value) {
227-
this._value = coerceNumberProperty(v);
227+
let value = coerceNumberProperty(v);
228+
229+
// While incrementing by a decimal we can end up with values like 33.300000000000004.
230+
// Truncate it to ensure that it matches the label and to make it easier to work with.
231+
if (this._roundToDecimal) {
232+
value = parseFloat(value.toFixed(this._roundToDecimal));
233+
}
234+
235+
this._value = value;
228236
this._percent = this._calculatePercentage(this._value);
229237

230238
// Since this also modifies the percentage, we need to let the change detection know.
@@ -638,17 +646,11 @@ export class MatSlider extends _MatSliderMixinBase
638646
} else if (percent === 1) {
639647
this.value = this.max;
640648
} else {
641-
let exactValue = this._calculateValue(percent);
649+
const exactValue = this._calculateValue(percent);
642650

643651
// This calculation finds the closest step by finding the closest
644652
// whole number divisible by the step relative to the min.
645-
let closestValue = Math.round((exactValue - this.min) / this.step) * this.step + this.min;
646-
647-
// If we've got a step with a decimal, we may end up with something like 33.300000000000004.
648-
// Truncate the value to ensure that it matches the label and to make it easier to work with.
649-
if (this._roundToDecimal) {
650-
closestValue = parseFloat(closestValue.toFixed(this._roundToDecimal));
651-
}
653+
const closestValue = Math.round((exactValue - this.min) / this.step) * this.step + this.min;
652654

653655
// The value needs to snap to the min and max.
654656
this.value = this._clamp(closestValue, this.min, this.max);

0 commit comments

Comments
 (0)