Skip to content

Commit

Permalink
fix(material/slider): Ticks updated wrongly if the max property 0 (#2…
Browse files Browse the repository at this point in the history
…4218)

* fix(material/slider): Ticks updated wrongly if the max property changed to 0

When we get equal min & max value for the slider then we can get division by zero which leads to an improper style value for the background-size (Infinity%). This fix introduces a tiny function that checks if we deal with finite numbers during calculations where potentially division by zero may occur.

Fixes #23913

* fix(material/slider): Check if interval persentage a valid number

Fixes #23913
  • Loading branch information
DMezhenskyi committed Jan 28, 2022
1 parent cad0872 commit c1f25bc
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
20 changes: 20 additions & 0 deletions src/material/slider/slider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,26 @@ describe('MatSlider', () => {
expect(sliderInstance.percent).toBe(1);
},
);
it('should properly update ticks when max value changed to 0', () => {
testComponent.min = 0;
testComponent.max = 100;
fixture.detectChanges();

dispatchMouseenterEvent(sliderNativeElement);
fixture.detectChanges();

expect(ticksElement.style.backgroundSize).toBe('6% 2px');
expect(ticksElement.style.transform).toContain('translateX(3%)');

testComponent.max = 0;
fixture.detectChanges();

dispatchMouseenterEvent(sliderNativeElement);
fixture.detectChanges();

expect(ticksElement.style.backgroundSize).toBe('0% 2px');
expect(ticksElement.style.transform).toContain('translateX(0%)');
});
});

describe('slider with set value', () => {
Expand Down
14 changes: 11 additions & 3 deletions src/material/slider/slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -860,15 +860,17 @@ export class MatSlider
return;
}

let tickIntervalPercent: number;
if (this.tickInterval == 'auto') {
let trackSize = this.vertical ? this._sliderDimensions.height : this._sliderDimensions.width;
let pixelsPerStep = (trackSize * this.step) / (this.max - this.min);
let stepsPerTick = Math.ceil(MIN_AUTO_TICK_SEPARATION / pixelsPerStep);
let pixelsPerTick = stepsPerTick * this.step;
this._tickIntervalPercent = pixelsPerTick / trackSize;
tickIntervalPercent = pixelsPerTick / trackSize;
} else {
this._tickIntervalPercent = (this.tickInterval * this.step) / (this.max - this.min);
tickIntervalPercent = (this.tickInterval * this.step) / (this.max - this.min);
}
this._tickIntervalPercent = isSafeNumber(tickIntervalPercent) ? tickIntervalPercent : 0;
}

/** Creates a slider change object from the specified value. */
Expand All @@ -883,7 +885,8 @@ export class MatSlider

/** Calculates the percentage of the slider that a value is. */
private _calculatePercentage(value: number | null) {
return ((value || 0) - this.min) / (this.max - this.min);
const percentage = ((value || 0) - this.min) / (this.max - this.min);
return isSafeNumber(percentage) ? percentage : 0;
}

/** Calculates the value a percentage of the slider corresponds to. */
Expand Down Expand Up @@ -954,6 +957,11 @@ export class MatSlider
}
}

/** Checks if number is safe for calculation */
function isSafeNumber(value: number) {
return !isNaN(value) && isFinite(value);
}

/** Returns whether an event is a touch event. */
function isTouchEvent(event: MouseEvent | TouchEvent): event is TouchEvent {
// This function is called for every pixel that the user has dragged so we need it to be
Expand Down

0 comments on commit c1f25bc

Please sign in to comment.