Skip to content

feat(slider): add the ability to apply custom formatting to thumb label #10243

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
Mar 6, 2018
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
11 changes: 9 additions & 2 deletions src/lib/slider/slider.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
`<mat-slider>` allows for the selection of a value from a range via mouse, touch, or keyboard,
`<mat-slider>` allows for the selection of a value from a range via mouse, touch, or keyboard,
similar to `<input type="range">`.

<!-- example(slider-overview) -->
Expand Down Expand Up @@ -27,7 +27,7 @@ on bottom and the maximum value on top.

An `invert` attribute is also available which can be specified to flip the axis that the thumb moves
along. An inverted horizontal slider will have the minimum value on the right and the maximum value
on the left, while an inverted vertical slider will have the minimum value on top and the maximum
on the left, while an inverted vertical slider will have the minimum value on top and the maximum
value on bottom.

```html
Expand All @@ -46,6 +46,13 @@ discrete value (such as a 1-5 rating).
<mat-slider thumbLabel tickInterval="1"></mat-slider>
```

### Formatting the thumb label
By default, the value in the slider's thumb label will be the same as the model value, however this
may end up being too large to fit into the label. If you want to control the value that is being
displayed, you can do so using the `displayWith` input.

<!-- example(slider-formatting) -->

### Tick marks
By default, sliders do not show tick marks along the thumb track. This can be enabled using the
`tickInterval` attribute. The value of `tickInterval` should be a number representing the number
Expand Down
53 changes: 53 additions & 0 deletions src/lib/slider/slider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ describe('MatSlider without forms', () => {
SliderWithTabIndexBinding,
SliderWithNativeTabindexAttr,
VerticalSlider,
SliderWithCustomThumbLabelFormatting,
],
providers: [
{provide: HAMMER_GESTURE_CONFIG, useFactory: () => {
Expand Down Expand Up @@ -602,6 +603,38 @@ describe('MatSlider without forms', () => {
});
});

describe('slider with custom thumb label formatting', () => {
let fixture: ComponentFixture<SliderWithCustomThumbLabelFormatting>;
let sliderInstance: MatSlider;
let thumbLabelTextElement: Element;

beforeEach(() => {
fixture = TestBed.createComponent(SliderWithCustomThumbLabelFormatting);
fixture.detectChanges();

const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider));
const sliderNativeElement = sliderDebugElement.nativeElement;
sliderInstance = sliderDebugElement.componentInstance;
thumbLabelTextElement = sliderNativeElement.querySelector('.mat-slider-thumb-label-text')!;
});

it('should invoke the passed-in `displayWith` function with the value', () => {
spyOn(fixture.componentInstance, 'displayWith').and.callThrough();

sliderInstance.value = 1337;
fixture.detectChanges();

expect(fixture.componentInstance.displayWith).toHaveBeenCalledWith(1337);
});

it('should format the thumb label based on the passed-in `displayWith` function', () => {
sliderInstance.value = 200000;
fixture.detectChanges();

expect(thumbLabelTextElement.textContent).toBe('200k');
});
});

describe('slider with value property binding', () => {
let fixture: ComponentFixture<SliderWithOneWayBinding>;
let sliderDebugElement: DebugElement;
Expand Down Expand Up @@ -1426,6 +1459,26 @@ class SliderWithSetTickInterval {
})
class SliderWithThumbLabel { }


@Component({
template: `<mat-slider min="1" max="100000" [displayWith]="displayWith" thumbLabel></mat-slider>`,
styles: [styles],
})
class SliderWithCustomThumbLabelFormatting {
displayWith(value: number | null) {
if (!value) {
return 0;
}

if (value >= 1000) {
return (value / 1000) + 'k';
}

return value;
}
}


@Component({
template: `<mat-slider [value]="val"></mat-slider>`,
styles: [styles],
Expand Down
11 changes: 11 additions & 0 deletions src/lib/slider/slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,13 @@ export class MatSlider extends _MatSliderMixinBase
}
private _value: number | null = null;

/**
* Function that will be used to format the value before it is displayed
* in the thumb label. Can be used to format very large number in order
* for them to fit into the slider thumb.
*/
@Input() displayWith: (value: number | null) => string | number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

displayWith is kind of a weird name. What about formatter or formatFunction?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with this one, because we use the same for the autocomplete.


/** Whether the slider is vertical. */
@Input()
get vertical(): boolean { return this._vertical; }
Expand All @@ -263,6 +270,10 @@ export class MatSlider extends _MatSliderMixinBase

/** The value to be used for display purposes. */
get displayValue(): string | number {
if (this.displayWith) {
return this.displayWith(this.value);
}

// Note that this could be improved further by rounding something like 0.999 to 1 or
// 0.899 to 0.9, however it is very performance sensitive, because it gets called on
// every change detection cycle.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mat-slider {
width: 300px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<mat-slider
thumbLabel
[displayWith]="formatLabel"
tickInterval="1000"
min="1"
max="100000"></mat-slider>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {Component} from '@angular/core';

/**
* @title Slider with custom thumb label formatting.
*/
@Component({
selector: 'slider-formatting-example',
templateUrl: 'slider-formatting-example.html',
styleUrls: ['slider-formatting-example.css'],
})
export class SliderFormattingExample {
formatLabel(value: number | null) {
if (!value) {
return 0;
}

if (value >= 1000) {
return Math.round(value / 1000) + 'k';
}

return value;
}
}