Skip to content

Commit d50fd3d

Browse files
crisbetojosephperrott
authored andcommitted
fix(slider): unable to slide to max value under certain conditions (#10364)
Fixes users not being to slide to the maximum value in a slider, in some cases, when the number of steps don't divide evenly into the maximum value. Fixes #10148.
1 parent 02f5256 commit d50fd3d

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

src/lib/slider/slider.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,18 @@ describe('MatSlider without forms', () => {
207207
it('should have aria-orientation horizontal', () => {
208208
expect(sliderNativeElement.getAttribute('aria-orientation')).toEqual('horizontal');
209209
});
210+
211+
it('should slide to the max value when the steps do not divide evenly into it', () => {
212+
sliderInstance.min = 5;
213+
sliderInstance.max = 100;
214+
sliderInstance.step = 15;
215+
216+
dispatchSlideEventSequence(sliderNativeElement, 0, 1, gestureConfig);
217+
fixture.detectChanges();
218+
219+
expect(sliderInstance.value).toBe(100);
220+
});
221+
210222
});
211223

212224
describe('disabled slider', () => {

src/lib/slider/slider.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -619,16 +619,29 @@ export class MatSlider extends _MatSliderMixinBase
619619

620620
// The exact value is calculated from the event and used to find the closest snap value.
621621
let percent = this._clamp((posComponent - offset) / size);
622+
622623
if (this._invertMouseCoords) {
623624
percent = 1 - percent;
624625
}
625-
let exactValue = this._calculateValue(percent);
626626

627-
// This calculation finds the closest step by finding the closest whole number divisible by the
628-
// step relative to the min.
629-
let closestValue = Math.round((exactValue - this.min) / this.step) * this.step + this.min;
630-
// The value needs to snap to the min and max.
631-
this.value = this._clamp(closestValue, this.min, this.max);
627+
// Since the steps may not divide cleanly into the max value, if the user
628+
// slid to 0 or 100 percent, we jump to the min/max value. This approach
629+
// is slightly more intuitive than using `Math.ceil` below, because it
630+
// follows the user's pointer closer.
631+
if (percent === 0) {
632+
this.value = this.min;
633+
} else if (percent === 1) {
634+
this.value = this.max;
635+
} else {
636+
let exactValue = this._calculateValue(percent);
637+
638+
// This calculation finds the closest step by finding the closest
639+
// whole number divisible by the step relative to the min.
640+
let closestValue = Math.round((exactValue - this.min) / this.step) * this.step + this.min;
641+
642+
// The value needs to snap to the min and max.
643+
this.value = this._clamp(closestValue, this.min, this.max);
644+
}
632645
}
633646

634647
/** Emits a change event if the current value is different from the last emitted value. */

0 commit comments

Comments
 (0)