Skip to content

Commit

Permalink
fix(material/slider): active vs inactive tick mark count (#30319)
Browse files Browse the repository at this point in the history
(cherry picked from commit 5f238ab)
  • Loading branch information
wagnermaciel committed Jan 14, 2025
1 parent 9490f1a commit 4f676d4
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 4 deletions.
85 changes: 83 additions & 2 deletions src/material/slider/slider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1549,6 +1549,7 @@ describe('MatSlider', () => {
let fixture: ComponentFixture<SliderWithTickMarks>;
let slider: MatSlider;
let sliderEl: HTMLElement;
let input: MatSliderThumb;

function getTickMarkEls() {
const activeClass = '.mdc-slider__tick-mark--active';
Expand All @@ -1565,6 +1566,7 @@ describe('MatSlider', () => {
const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider));
slider = sliderDebugElement.componentInstance;
sliderEl = sliderDebugElement.nativeElement;
input = slider._getInput(_MatThumb.END) as MatSliderThumb;
}));

it('should have tick marks', () => {
Expand Down Expand Up @@ -1604,15 +1606,80 @@ describe('MatSlider', () => {
}
});

// TODO(wagnermaciel): Add this test once this is fixed.
// it('should render the correct number of active & inactive ticks', () => {});
it('should render the correct number of active & inactive ticks', () => {
let tickEls = getTickMarkEls();
expect(tickEls.active.length).toBe(1);
expect(tickEls.inactive.length).toBe(100);

input.value = 50;
tickEls = getTickMarkEls();
expect(tickEls.active.length).toBe(51);
expect(tickEls.inactive.length).toBe(50);

input.value = 100;
tickEls = getTickMarkEls();
expect(tickEls.active.length).toBe(101);
expect(tickEls.inactive.length).toBe(0);
});

// TODO(wagnermaciel): Add this test once this is fixed.
// it('should position the tick marks correctly with a misaligned step', () => {});

// TODO(wagnermaciel): Add this test once this is fixed.
// it('should position the tick marks correctly with a misaligned step (rtl)', () => {});
});

describe('range slider with tick marks', () => {
let fixture: ComponentFixture<RangeSliderWithTickMarks>;
let slider: MatSlider;
let sliderEl: HTMLElement;
let endInput: MatSliderRangeThumb;
let startInput: MatSliderRangeThumb;

function getTickMarkEls() {
const activeClass = '.mdc-slider__tick-mark--active';
const inactiveClass = '.mdc-slider__tick-mark--inactive';
const active = sliderEl.querySelectorAll(activeClass);
const inactive = sliderEl.querySelectorAll(inactiveClass);
const ticks = sliderEl.querySelectorAll(`${activeClass},${inactiveClass}`);
return {ticks, active, inactive};
}

beforeEach(waitForAsync(() => {
fixture = createComponent(RangeSliderWithTickMarks);
fixture.detectChanges();
const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider));
slider = sliderDebugElement.componentInstance;
sliderEl = sliderDebugElement.nativeElement;
endInput = slider._getInput(_MatThumb.END) as MatSliderRangeThumb;
startInput = slider._getInput(_MatThumb.START) as MatSliderRangeThumb;
}));

it('should render the correct number of active & inactive ticks', () => {
startInput.value = 0;
endInput.value = 100;

let tickEls = getTickMarkEls();
expect(tickEls.active.length).toBe(101);
expect(tickEls.inactive.length).toBe(0);

startInput.value = 25;
tickEls = getTickMarkEls();
expect(tickEls.active.length).toBe(76);
expect(tickEls.inactive.length).toBe(25);

endInput.value = 75;
tickEls = getTickMarkEls();
expect(tickEls.active.length).toBe(51);
expect(tickEls.inactive.length).toBe(50);

startInput.value = 50;
endInput.value = 50;
tickEls = getTickMarkEls();
expect(tickEls.active.length).toBe(1);
expect(tickEls.inactive.length).toBe(100);
});
});
});

const SLIDER_STYLES = ['.mat-mdc-slider { width: 300px; }'];
Expand Down Expand Up @@ -1917,6 +1984,20 @@ class SliderWithTickMarks {
@ViewChild(MatSlider) slider: MatSlider;
}

@Component({
template: `
<mat-slider [showTickMarks]="true">
<input matSliderStartThumb>
<input matSliderEndThumb>
</mat-slider>
`,
styles: SLIDER_STYLES,
standalone: false,
})
class RangeSliderWithTickMarks {
@ViewChild(MatSlider) slider: MatSlider;
}

/** Clicks on the MatSlider at the coordinates corresponding to the given value. */
function setValueByClick(
slider: MatSlider,
Expand Down
4 changes: 2 additions & 2 deletions src/material/slider/slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -885,8 +885,8 @@ export class MatSlider implements AfterViewInit, OnDestroy, _MatSlider {

private _updateTickMarkUINonRange(step: number): void {
const value = this._getValue();
let numActive = Math.max(Math.round((value - this.min) / step), 0);
let numInactive = Math.max(Math.round((this.max - value) / step), 0);
let numActive = Math.max(Math.round((value - this.min) / step), 0) + 1;
let numInactive = Math.max(Math.round((this.max - value) / step), 0) - 1;
this._isRtl ? numActive++ : numInactive++;

this._tickMarks = Array(numActive)
Expand Down

0 comments on commit 4f676d4

Please sign in to comment.