Skip to content

Commit ff84842

Browse files
mmalerbajelbourn
authored andcommitted
fix(slider): update thumb pos & ticks when min/max change (#1598)
1 parent 8f50c35 commit ff84842

File tree

4 files changed

+63
-6
lines changed

4 files changed

+63
-6
lines changed

src/demo-app/slider/slider-demo.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ <h1>Default Slider</h1>
33
{{slidey.value}}
44

55
<h1>Slider with Min and Max</h1>
6-
<md-slider min="5" max="7" #slider2></md-slider>
6+
<input [(ngModel)]="min">
7+
<md-slider [min]="min" [max]="max" tick-interval="5" #slider2></md-slider>
78
{{slider2.value}}
9+
<input [(ngModel)]="max">
810

911
<h1>Disabled Slider</h1>
1012
<md-slider disabled #slider3></md-slider>

src/demo-app/slider/slider-demo.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ import {Component} from '@angular/core';
99
export class SliderDemo {
1010
demo: number;
1111
val: number = 50;
12+
min: number = 0;
13+
max: number = 100;
1214
}

src/lib/slider/slider.spec.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,18 +251,23 @@ describe('MdSlider', () => {
251251
let sliderDimensions: ClientRect;
252252
let trackFillElement: HTMLElement;
253253
let thumbElement: HTMLElement;
254+
let tickContainerElement: HTMLElement;
255+
let testComponent: SliderWithMinAndMax;
254256

255257
beforeEach(() => {
256258
fixture = TestBed.createComponent(SliderWithMinAndMax);
257259
fixture.detectChanges();
258260

259261
sliderDebugElement = fixture.debugElement.query(By.directive(MdSlider));
262+
testComponent = fixture.debugElement.componentInstance;
260263
sliderNativeElement = sliderDebugElement.nativeElement;
261264
sliderInstance = sliderDebugElement.injector.get(MdSlider);
262265
sliderTrackElement = <HTMLElement>sliderNativeElement.querySelector('.md-slider-track');
263266
sliderDimensions = sliderTrackElement.getBoundingClientRect();
264267
trackFillElement = <HTMLElement>sliderNativeElement.querySelector('.md-slider-track-fill');
265268
thumbElement = <HTMLElement>sliderNativeElement.querySelector('.md-slider-thumb-position');
269+
tickContainerElement =
270+
<HTMLElement>sliderNativeElement.querySelector('.md-slider-tick-container');
266271
});
267272

268273
it('should set the default values from the attributes', () => {
@@ -314,7 +319,39 @@ describe('MdSlider', () => {
314319
// The closest snap is at the halfway point on the slider.
315320
expect(thumbDimensions.left).toBe(sliderDimensions.left + sliderDimensions.width * 0.5);
316321
expect(trackFillDimensions.width).toBe(thumbPosition);
322+
});
323+
324+
it('should adjust thumb and ticks when min changes', () => {
325+
testComponent.min = -2;
326+
fixture.detectChanges();
317327

328+
let trackFillDimensions = trackFillElement.getBoundingClientRect();
329+
let tickContainerDimensions = tickContainerElement.getBoundingClientRect();
330+
331+
expect(trackFillDimensions.width).toBe(sliderDimensions.width * 6 / 8);
332+
expect(tickContainerDimensions.width)
333+
.toBe(sliderDimensions.width - sliderDimensions.width * 6 / 8);
334+
expect(tickContainerElement.style.background)
335+
.toContain(`repeating-linear-gradient(to right, black, black 2px, transparent 2px, ` +
336+
`transparent ${sliderDimensions.width * 6 / 8 - 1}px)`);
337+
});
338+
339+
it('should adjust thumb and ticks when max changes', () => {
340+
testComponent.min = -2;
341+
fixture.detectChanges();
342+
343+
testComponent.max = 10;
344+
fixture.detectChanges();
345+
346+
let trackFillDimensions = trackFillElement.getBoundingClientRect();
347+
let tickContainerDimensions = tickContainerElement.getBoundingClientRect();
348+
349+
expect(trackFillDimensions.width).toBe(sliderDimensions.width * 6 / 12);
350+
expect(tickContainerDimensions.width)
351+
.toBe(sliderDimensions.width - sliderDimensions.width * 6 / 12);
352+
expect(tickContainerElement.style.background)
353+
.toContain(`repeating-linear-gradient(to right, black, black 2px, transparent 2px, ` +
354+
`transparent ${sliderDimensions.width * 6 / 12 - 1}px)`);
318355
});
319356
});
320357

@@ -767,11 +804,14 @@ class StandardSlider { }
767804
class DisabledSlider { }
768805

769806
@Component({
770-
template: `<md-slider min="4" max="6"></md-slider>`,
807+
template: `<md-slider [min]="min" [max]="max" tick-interval="6"></md-slider>`,
771808
styles: [noTransitionStyle],
772809
encapsulation: ViewEncapsulation.None
773810
})
774-
class SliderWithMinAndMax { }
811+
class SliderWithMinAndMax {
812+
min = 4;
813+
max = 6;
814+
}
775815

776816
@Component({
777817
template: `<md-slider value="26"></md-slider>`

src/lib/slider/slider.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ export class MdSlider implements AfterContentInit, ControlValueAccessor {
126126
if (!this._isInitialized) {
127127
this.value = this._min;
128128
}
129+
this.snapThumbToValue();
130+
this._updateTickSeparation();
129131
}
130132

131133
@Input()
@@ -136,6 +138,8 @@ export class MdSlider implements AfterContentInit, ControlValueAccessor {
136138

137139
set max(v: number) {
138140
this._max = Number(v);
141+
this.snapThumbToValue();
142+
this._updateTickSeparation();
139143
}
140144

141145
@Input()
@@ -277,6 +281,9 @@ export class MdSlider implements AfterContentInit, ControlValueAccessor {
277281
* is set to something other than a number or 'auto', nothing happens.
278282
*/
279283
private _updateTickSeparation() {
284+
if (!this._sliderDimensions) {
285+
return;
286+
}
280287
if (this._tickInterval == 'auto') {
281288
this._updateAutoTickSeparation();
282289
} else if (Number(this._tickInterval)) {
@@ -429,8 +436,10 @@ export class SliderRenderer {
429436
* Draws ticks onto the tick container.
430437
*/
431438
drawTicks(tickSeparation: number) {
439+
let sliderTrackContainer =
440+
<HTMLElement>this._sliderElement.querySelector('.md-slider-track-container');
441+
let tickContainerWidth = sliderTrackContainer.getBoundingClientRect().width;
432442
let tickContainer = <HTMLElement>this._sliderElement.querySelector('.md-slider-tick-container');
433-
let tickContainerWidth = tickContainer.getBoundingClientRect().width;
434443
// An extra element for the last tick is needed because the linear gradient cannot be told to
435444
// always draw a tick at the end of the gradient. To get around this, there is a second
436445
// container for ticks that has a single tick mark on the very right edge.
@@ -444,10 +453,14 @@ export class SliderRenderer {
444453
lastTickContainer.style.background = `linear-gradient(to left, black, black 2px, transparent ` +
445454
`2px, transparent)`;
446455

447-
// If the second to last tick is too close (a separation of less than half the normal
448-
// separation), don't show it by decreasing the width of the tick container element.
449456
if (tickContainerWidth % tickSeparation < (tickSeparation / 2)) {
457+
// If the second to last tick is too close (a separation of less than half the normal
458+
// separation), don't show it by decreasing the width of the tick container element.
450459
tickContainer.style.width = tickContainerWidth - tickSeparation + 'px';
460+
} else {
461+
// If there is enough space for the second-to-last tick, restore the default width of the
462+
// tick container.
463+
tickContainer.style.width = '';
451464
}
452465
}
453466
}

0 commit comments

Comments
 (0)