Skip to content

fix(material/slider): active vs inactive tick mark count #30319

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading