Installation
import { WrSlider } from 'ngwr/slider';
@Component({ imports: [WrSlider, FormsModule] })
export class MyComponent {
protected volume = 35;
}Single value
The default. Bind a number through any form mechanism.
<wr-slider [(value)]="volume" min="0" max="100" /><wr-slider [(value)]='volume' min='0' max='100' />Range
Set range to render two thumbs. The bound value is [low, high].
<wr-slider [(value)]="priceRange" range min="0" max="1000" step="50" /><wr-slider [(value)]='priceRange' range min='0' max='1000' step='50' />Step
The thumb snaps to the nearest multiple of step.
<wr-slider [(value)]='stepped' min='0' max='100' step='25' />Disabled
<wr-slider [(value)]='volume' disabled />Keyboard
The thumb is a real <button> with role='slider' — full keyboard support out of the box. Arrow keys step by step; Shift + arrow or PageUp / PageDown step by step × 10; Home / End jump to min / max.
Values outside the range, and `null`
[min] and [max] bound what the thumb can produce and where it can be drawn. A value written in from a form is clamped for the display only — the model keeps exactly what you set.
Set 155 on a slider bound with max="100" and the thumb parks at the top of its track and announces aria-valuenow="100", while control.value stays 155. The asymmetry is deliberate and matches wr-rating and wr-input-number: a thumb cannot render off its own track, so the display has no choice — but writing that clamp back into the model would delete the out-of-range value a Validators.max exists to report, and would mark a pristine form dirty on first paint. The first drag or arrow key commits an in-range number and the two agree from then on.
WrSliderValue is number | [number, number] — there is no empty state. A slider always points somewhere, so a value that is neither shape is ignored and the thumb stays where it was: control.reset(), which resets to null by default, leaves the thumb on the old position. Reset to a number instead — control.reset(0), or whatever your min is. In range mode, a scalar written to a two-thumb slider seeds the high thumb at max and, again, leaves the model holding the scalar you gave it until a thumb moves.
The reactive-forms guide has the same table for every value control, next to the two bridge behaviours that surprise people more: updateOn does not apply, and a { emitEvent: false } write does not repaint.
API
| Name | Description | Type | Default |
|---|---|---|---|
min | Lower bound. | WrSliderValue | undefined | 0 |
max | Upper bound. | WrSliderValue | undefined | 100 |
step | Step size for keyboard and drag. | number | 1 |
range | Render two thumbs and emit [low, high]. | boolean | false |
disabled | Disable interaction. Bound automatically from the field's disabled state when used with [formField]. | boolean | false |
readonly | Refuse value changes while the thumbs stay focusable and the value still submits. Bound automatically from the field's readonly state when used with [formField]. The thumbs keep their tab stop and keep announcing their value — arrow keys, Home / End and the pointer simply move nothing — which is the whole difference from disabled, where they would leave the tab order entirely. Mirrored as aria-readonly, which role slider supports. | boolean | false |
showLabel | Render the current value below the track. | boolean | true |
ariaLabel | Accessible name of the thumb — the single one, or the LOWER one in range mode. Falls back to slider.label / slider.lower. | string | null | null |
upperLabel | Accessible name of the upper thumb in range mode. Falls back to slider.upper. | string | null | null |
value | Current value. Bound by [formField], or two-way via [(value)]. Shape follows range: a plain number, or [low, high] in range mode. | WrSliderValue | 0 |
(touch) | Emitted on blur so a bound field can mark itself touched. | void | — |
CSS variables
Custom properties ngwr/slider publishes. Each default below is declared on the component's own selector, so a :root override is shadowed by it — set them on that selector, on a wrapper you scope yourself, or inline on the element. Unlike the BEM class names, these are the supported way to restyle the component.
| Variable | Default | Declared on |
|---|---|---|
--wr-slider-fill | var(--wr-color-primary) | .wr-slider +1 variant override |
--wr-slider-label | var(--wr-color-on-surface-muted) | .wr-slider |
--wr-slider-thumb | var(--wr-color-surface) | .wr-slider |
--wr-slider-thumb-border | var(--wr-color-primary) | .wr-slider +1 variant override |
--wr-slider-thumb-size | 1rem | .wr-slider |
--wr-slider-track | var(--wr-color-outline) | .wr-slider |
--wr-slider-track-height | 0.25rem | .wr-slider |