Skip to content

Commit 23b22bc

Browse files
committed
fix(slider): add disabled state
1 parent 50d6f3a commit 23b22bc

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

src/slider/slider.component.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
4747
@Component({
4848
selector: "ibm-slider",
4949
template: `
50-
<div class="bx--slider">
50+
<div
51+
class="bx--slider"
52+
[ngClass]="{'bx--slider--disabled': disabled}">
5153
<div
5254
#thumb
5355
class="bx--slider__thumb"
@@ -114,7 +116,7 @@ export class Slider implements AfterViewInit, OnDestroy, ControlValueAccessor {
114116
this.slidAmount = this.convertToPx(v);
115117

116118
if (this.input) {
117-
this.input.value = v;
119+
this.input.value = v.toString();
118120
}
119121

120122
this.propagateChange(v);
@@ -129,8 +131,18 @@ export class Slider implements AfterViewInit, OnDestroy, ControlValueAccessor {
129131
/** Value used to "multiply" the `step` when using arrow keys to select values */
130132
@Input() shiftMultiplier = 4;
131133
/** Disables the range visually and functionally */
132-
// TODO: implement disabled state
133-
@Input() disabled = false;
134+
@Input() set disabled(v) {
135+
this._disabled = v;
136+
// for some reason `this.input` never exists here, so we have to query for it here too
137+
const input = this.elementRef.nativeElement.querySelector("input:not([type=range])");
138+
if (input) {
139+
input.disabled = v;
140+
}
141+
}
142+
143+
get disabled() {
144+
return this._disabled;
145+
}
134146
/** Emits every time a new value is selected */
135147
@Output() valueChange: EventEmitter<number> = new EventEmitter();
136148
@HostBinding("class.bx--slider-container") hostClass = true;
@@ -145,8 +157,9 @@ export class Slider implements AfterViewInit, OnDestroy, ControlValueAccessor {
145157
/** Array of event subscriptions so we can batch unsubscribe in `ngOnDestroy` */
146158
protected eventSubscriptions: Array<Subscription> = [];
147159
protected slidAmount = 0;
148-
protected input;
160+
protected input: HTMLInputElement;
149161
protected _value = 0;
162+
protected _disabled = false;
150163

151164
constructor(protected elementRef: ElementRef) {}
152165

@@ -164,7 +177,7 @@ export class Slider implements AfterViewInit, OnDestroy, ControlValueAccessor {
164177
this.input.classList.add("bx--slider-text-input");
165178
this.input.classList.add("bx--text-input");
166179
this.input.setAttribute("aria-labelledby", `${this.bottomRangeId} ${this.topRangeId}`);
167-
this.input.value = this.value;
180+
this.input.value = this.value.toString();
168181
// bind events on our optional input
169182
this.eventSubscriptions.push(fromEvent(this.input, "change").subscribe(this.onChange.bind(this)));
170183
this.eventSubscriptions.push(fromEvent(this.input, "focus").subscribe(this.onFocus.bind(this)));
@@ -260,6 +273,7 @@ export class Slider implements AfterViewInit, OnDestroy, ControlValueAccessor {
260273

261274
/** Handles clicks on the range track, and setting the value to it's "real" equivilent */
262275
onClick(event) {
276+
if (this.disabled) { return; }
263277
const trackLeft = this.track.nativeElement.getBoundingClientRect().left;
264278
this.value = this.convertToValue(event.clientX - trackLeft);
265279
console.log(event);
@@ -272,6 +286,7 @@ export class Slider implements AfterViewInit, OnDestroy, ControlValueAccessor {
272286

273287
/** Mouse move handler. Responsible for updating the value and visual selection based on mouse movement */
274288
onMouseMove(event) {
289+
if (this.disabled) { return; }
275290
if (this.isMouseDown) {
276291
const trackWidth = this.track.nativeElement.getBoundingClientRect().width;
277292
const trackLeft = this.track.nativeElement.getBoundingClientRect().left;
@@ -288,6 +303,7 @@ export class Slider implements AfterViewInit, OnDestroy, ControlValueAccessor {
288303
/** Enables the `onMouseMove` handler */
289304
onMouseDown(event) {
290305
event.preventDefault();
306+
if (this.disabled) { return; }
291307
this.thumb.nativeElement.focus();
292308
this.isMouseDown = true;
293309
}

src/slider/slider.stories.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { storiesOf, moduleMetadata } from "@storybook/angular";
22
import { action } from "@storybook/addon-actions";
3-
import { withKnobs, number, text } from "@storybook/addon-knobs/angular";
3+
import { withKnobs, number, text, boolean } from "@storybook/addon-knobs/angular";
44

55
import { SliderModule } from "./slider.module";
66

@@ -9,7 +9,10 @@ storiesOf("Slider", module).addDecorator(moduleMetadata({
99
}))
1010
.addDecorator(withKnobs)
1111
.add("Basic", () => ({
12-
template: "<ibm-slider></ibm-slider>"
12+
template: `<ibm-slider [disabled]="disabled"></ibm-slider>`,
13+
props: {
14+
disabled: boolean("disabled", false)
15+
}
1316
}))
1417
.add("Advanced", () => ({
1518
template: `
@@ -19,6 +22,7 @@ storiesOf("Slider", module).addDecorator(moduleMetadata({
1922
[step]="step"
2023
[value]="value"
2124
[shiftMultiplier]="shiftMultiplier"
25+
[disabled]="disabled"
2226
(valueChange)="valueChange($event)">
2327
<span minLabel>{{minLabel}}</span>
2428
<span maxLabel>{{maxLabel}}</span>
@@ -32,17 +36,19 @@ storiesOf("Slider", module).addDecorator(moduleMetadata({
3236
value: number("value", 0),
3337
minLabel: text("minLabel", "0"),
3438
maxLabel: text("maxLabel", "100"),
39+
disabled: boolean("disabled", false),
3540
shiftMultiplier: number("shiftMultiplier", 4),
3641
valueChange: action("Value changed")
3742
}
3843
}))
3944
.add("With NgModel", () => ({
4045
template: `
41-
<ibm-slider [(ngModel)]="model"></ibm-slider>
46+
<ibm-slider [(ngModel)]="model" [disabled]="disabled"></ibm-slider>
4247
<br>
4348
<span>model: {{model}}</span>
4449
`,
4550
props: {
46-
model: 0
51+
model: 0,
52+
disabled: boolean("disabled", false)
4753
}
4854
}));

0 commit comments

Comments
 (0)