Skip to content

Commit 783dbb3

Browse files
feloyjelbourn
authored andcommitted
fix(slider): clamp thumb between min and max (#1617)
Fixes #1557
1 parent 572b36e commit 783dbb3

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

src/lib/slider/slider.spec.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ describe('MdSlider', () => {
2424
SliderWithThumbLabel,
2525
SliderWithOneWayBinding,
2626
SliderWithTwoWayBinding,
27+
SliderWithValueSmallerThanMin,
28+
SliderWithValueGreaterThanMax,
2729
],
2830
providers: [
2931
{provide: HAMMER_GESTURE_CONFIG, useFactory: () => {
@@ -670,6 +672,82 @@ describe('MdSlider', () => {
670672
expect(thumbPosition).toBe(sliderDimensions.width * 3 / 4);
671673
});
672674
});
675+
676+
describe('slider with set min and max and a value smaller than min', () => {
677+
let fixture: ComponentFixture<SliderWithValueSmallerThanMin>;
678+
let sliderDebugElement: DebugElement;
679+
let sliderNativeElement: HTMLElement;
680+
let sliderInstance: MdSlider;
681+
let sliderTrackElement: HTMLElement;
682+
let sliderDimensions: ClientRect;
683+
let thumbElement: HTMLElement;
684+
let thumbDimensions: ClientRect;
685+
686+
beforeEach(() => {
687+
688+
fixture = TestBed.createComponent(SliderWithValueSmallerThanMin);
689+
fixture.detectChanges();
690+
691+
sliderDebugElement = fixture.debugElement.query(By.directive(MdSlider));
692+
sliderNativeElement = sliderDebugElement.nativeElement;
693+
sliderInstance = sliderDebugElement.componentInstance;
694+
695+
sliderTrackElement = <HTMLElement>sliderNativeElement.querySelector('.md-slider-track');
696+
sliderDimensions = sliderTrackElement.getBoundingClientRect();
697+
698+
thumbElement = <HTMLElement>sliderNativeElement.querySelector('.md-slider-thumb-position');
699+
thumbDimensions = thumbElement.getBoundingClientRect();
700+
});
701+
702+
it('should set the value smaller than the min value', () => {
703+
expect(sliderInstance.value).toBe(3);
704+
expect(sliderInstance.min).toBe(4);
705+
expect(sliderInstance.max).toBe(6);
706+
});
707+
708+
it('should place the thumb on the min value', () => {
709+
thumbDimensions = thumbElement.getBoundingClientRect();
710+
expect(thumbDimensions.left).toBe(sliderDimensions.left);
711+
});
712+
});
713+
714+
describe('slider with set min and max and a value greater than max', () => {
715+
let fixture: ComponentFixture<SliderWithValueSmallerThanMin>;
716+
let sliderDebugElement: DebugElement;
717+
let sliderNativeElement: HTMLElement;
718+
let sliderInstance: MdSlider;
719+
let sliderTrackElement: HTMLElement;
720+
let sliderDimensions: ClientRect;
721+
let thumbElement: HTMLElement;
722+
let thumbDimensions: ClientRect;
723+
724+
beforeEach(() => {
725+
fixture = TestBed.createComponent(SliderWithValueGreaterThanMax);
726+
fixture.detectChanges();
727+
728+
sliderDebugElement = fixture.debugElement.query(By.directive(MdSlider));
729+
sliderNativeElement = sliderDebugElement.nativeElement;
730+
sliderInstance = sliderDebugElement.componentInstance;
731+
732+
sliderTrackElement = <HTMLElement>sliderNativeElement.querySelector('.md-slider-track');
733+
sliderDimensions = sliderTrackElement.getBoundingClientRect();
734+
735+
thumbElement = <HTMLElement>sliderNativeElement.querySelector('.md-slider-thumb-position');
736+
thumbDimensions = thumbElement.getBoundingClientRect();
737+
738+
});
739+
740+
it('should set the value greater than the max value', () => {
741+
expect(sliderInstance.value).toBe(7);
742+
expect(sliderInstance.min).toBe(4);
743+
expect(sliderInstance.max).toBe(6);
744+
});
745+
746+
it('should place the thumb on the max value', () => {
747+
thumbDimensions = thumbElement.getBoundingClientRect();
748+
expect(thumbDimensions.left).toBe(sliderDimensions.right);
749+
});
750+
});
673751
});
674752

675753
// The transition has to be removed in order to test the updated positions without setTimeout.
@@ -734,6 +812,20 @@ class SliderWithTwoWayBinding {
734812
control = new FormControl('');
735813
}
736814

815+
@Component({
816+
template: `<md-slider value="3" min="4" max="6"></md-slider>`,
817+
styles: [noTransitionStyle],
818+
encapsulation: ViewEncapsulation.None
819+
})
820+
class SliderWithValueSmallerThanMin { }
821+
822+
@Component({
823+
template: `<md-slider value="7" min="4" max="6"></md-slider>`,
824+
styles: [noTransitionStyle],
825+
encapsulation: ViewEncapsulation.None
826+
})
827+
class SliderWithValueGreaterThanMax { }
828+
737829
/**
738830
* Dispatches a click event from an element.
739831
* Note: The mouse event truncates the position for the click.

src/lib/slider/slider.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,8 @@ export class MdSlider implements AfterContentInit, ControlValueAccessor {
267267
snapThumbToValue() {
268268
this.updatePercentFromValue();
269269
if (this._sliderDimensions) {
270-
this._renderer.updateThumbAndFillPosition(this._percent, this._sliderDimensions.width);
270+
let renderedPercent = this.clamp(this._percent);
271+
this._renderer.updateThumbAndFillPosition(renderedPercent, this._sliderDimensions.width);
271272
}
272273
}
273274

0 commit comments

Comments
 (0)