Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

Commit 5326bf0

Browse files
committed
feat(slider): Adds value property to the component and foundation
1 parent 43ebd46 commit 5326bf0

File tree

5 files changed

+108
-42
lines changed

5 files changed

+108
-42
lines changed

packages/mdc-slider/README.md

+15
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ respectively.
114114

115115
Cleans up handlers when slider is destroyed
116116

117+
##### MDCCheckbox.value
118+
119+
String. Returns the slider's value. Setting this property will update the underlying input control.
120+
element.
121+
117122

118123
### Slider Events
119124

@@ -153,6 +158,16 @@ Returns a boolean specifying whether or not the input is disabled.
153158

154159
Updates the input's disabled state.
155160

161+
##### MDCCheckboxFoundation.getValue() => string
162+
163+
Returns the value of `adapter.getNativeControl().value`. Returns `null` if `getNativeControl()`
164+
does not return an object.
165+
166+
##### MDCCheckboxFoundation.setValue(value: string) => void
167+
168+
Sets the value of `adapter.getNativeControl().value`. Does nothing if `getNativeControl()` does
169+
not return an object.
170+
156171
### Theming
157172

158173
MDC Slider components use the configured theme's primary color for its thumb and track.

packages/mdc-slider/continuous/foundation.js

+26-16
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,22 @@ export default class MDCSliderFoundation extends MDCFoundation {
3030

3131
static get defaultAdapter() {
3232
return {
33-
addClass: ( /* className: string */ ) => {},
34-
removeClass: ( /* className: string */ ) => {},
35-
hasClass: ( /* className: string */ ) => {},
36-
addInputClass: ( /* className: string */ ) => {},
37-
removeInputClass: ( /* className: string */ ) => {},
38-
getNativeInput: ( /* HTMLInputElement */ ) => {},
39-
registerHandler: ( /* type: string, handler: EventListener */ ) => {},
40-
deregisterHandler: ( /* type: string, handler: EventListener */ ) => {},
41-
registerRootHandler: ( /* type: string, handler: EventListener */ ) => {},
42-
deregisterRootHandler: ( /* type: string, handler: EventListener */ ) => {},
43-
setAttr: ( /* name: string, value: string */ ) => {},
44-
setLowerStyle: ( /* name: string, value: number */ ) => {},
45-
setUpperStyle: ( /* name: string, value: number */ ) => {},
46-
hasNecessaryDom: ( /* boolean */ ) => false,
47-
notifyChange: ( /* evtData: {value: number} */ ) => {},
48-
detectIsIE: ( /* boolean */ ) => {},
33+
addClass: (/* className: string */) => {},
34+
removeClass: (/* className: string */) => {},
35+
hasClass: (/* className: string */) => {},
36+
addInputClass: (/* className: string */) => {},
37+
removeInputClass: (/* className: string */) => {},
38+
getNativeInput: (/* HTMLInputElement */) => {},
39+
registerHandler: (/* type: string, handler: EventListener */) => {},
40+
deregisterHandler: (/* type: string, handler: EventListener */) => {},
41+
registerRootHandler: (/* type: string, handler: EventListener */) => {},
42+
deregisterRootHandler: (/* type: string, handler: EventListener */) => {},
43+
setAttr: (/* name: string, value: string */) => {},
44+
setLowerStyle: (/* name: string, value: number */) => {},
45+
setUpperStyle: (/* name: string, value: number */) => {},
46+
hasNecessaryDom: (/* boolean */) => false,
47+
notifyChange: (/* evtData: {value: number} */) => {},
48+
detectIsIE: (/* boolean */) => {},
4949
};
5050
}
5151

@@ -218,6 +218,16 @@ export default class MDCSliderFoundation extends MDCFoundation {
218218
getNativeInput() {
219219
return this.adapter_.getNativeInput() || {
220220
disabled: false,
221+
value: null,
221222
};
222223
}
224+
225+
getValue() {
226+
return this.getNativeInput().value;
227+
}
228+
229+
setValue(value) {
230+
this.getNativeInput().value = value;
231+
this.updateValueStyles_();
232+
}
223233
}

packages/mdc-slider/continuous/index.js

+8
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,12 @@ export class MDCSlider extends MDCComponent {
7575
set disabled(disabled) {
7676
this.foundation_.setDisabled(disabled);
7777
}
78+
79+
get value() {
80+
return this.foundation_.getValue();
81+
}
82+
83+
set value(value) {
84+
this.foundation_.setValue(value);
85+
}
7886
}

test/unit/mdc-slider/foundation.test.js

+26
Original file line numberDiff line numberDiff line change
@@ -351,3 +351,29 @@ test('on mouseup calls target.blur()', () => {
351351
handlers.mouseup(evt);
352352
td.verify(evt.target.blur());
353353
});
354+
355+
test('#getValue returns the value of getNativeInput.value', () => {
356+
const { foundation, mockAdapter } = setupTest();
357+
td.when(mockAdapter.getNativeInput()).thenReturn({ value: 'value' });
358+
assert.equal(foundation.getValue(), 'value');
359+
});
360+
361+
test('#getValue returns null if getNativeInput() does not return anything', () => {
362+
const { foundation, mockAdapter } = setupTest();
363+
td.when(mockAdapter.getNativeInput()).thenReturn(null);
364+
assert.isNull(foundation.getValue());
365+
});
366+
367+
test('#setValue sets the value of getNativeInput.value', () => {
368+
const { foundation, mockAdapter } = setupTest();
369+
const nativeControl = { value: null, max: 100, min: 0 };
370+
td.when(mockAdapter.getNativeInput()).thenReturn(nativeControl);
371+
foundation.setValue('49');
372+
assert.equal(nativeControl.value, '49');
373+
});
374+
375+
test('#setValue exits gracefully if getNativeInput() does not return anything', () => {
376+
const { foundation, mockAdapter } = setupTest();
377+
td.when(mockAdapter.getNativeInput()).thenReturn(null);
378+
assert.doesNotThrow(() => foundation.setValue('new value'));
379+
});

test/unit/mdc-slider/mdc-slider.test.js

+33-26
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@
1414
* limitations under the License.
1515
*/
1616

17-
import {assert} from 'chai';
17+
/* eslint object-curly-spacing: [error, always, { "objectsInObjects": false }], arrow-parens: [error, as-needed] */
18+
19+
import { assert } from 'chai';
1820
import bel from 'bel';
1921
import domEvents from 'dom-events';
2022
import td from 'testdouble';
21-
22-
import {MDCSlider} from '../../../packages/mdc-slider';
23+
import { strings } from '../../../packages/mdc-slider/continuous/constants';
24+
import { MDCSlider } from '../../../packages/mdc-slider';
2325

2426
function getFixture() {
2527
return bel`
2628
<div class="mdc-slider">
27-
<input type="range" class="mdc-slider__input">
29+
<input type="range" class="mdc-slider__input" min="0" max="100">
2830
<div class="mdc-slider__background">
2931
<div class="mdc-slider__background-lower"></div>
3032
<div class="mdc-slider__background-upper"></div>
@@ -42,11 +44,11 @@ test('attachTo returns a component instance', () => {
4244
function setupTest() {
4345
const root = getFixture();
4446
const component = new MDCSlider(root);
45-
return {root, component};
47+
return { root, component };
4648
}
4749

4850
test('get/set disabled updates the input element', () => {
49-
const {root, component} = setupTest();
51+
const { root, component } = setupTest();
5052
const input = root.querySelector('.mdc-slider__input');
5153
component.disabled = true;
5254
assert.isOk(input.disabled);
@@ -55,109 +57,114 @@ test('get/set disabled updates the input element', () => {
5557
});
5658

5759
test('get disabled gets state', () => {
58-
const {component} = setupTest();
60+
const { component } = setupTest();
5961
component.disabled = true;
6062
assert.isOk(component.disabled);
6163
component.disabled = false;
6264
assert.isNotOk(component.disabled);
6365
});
6466

6567
test('#adapter.addClass adds a class to the root element', () => {
66-
const {root, component} = setupTest();
68+
const { root, component } = setupTest();
6769
component.getDefaultFoundation().adapter_.addClass('foo');
6870
assert.isOk(root.classList.contains('foo'));
6971
});
7072

7173
test('#adapter.removeClass removes a class from the root element', () => {
72-
const {root, component} = setupTest();
74+
const { root, component } = setupTest();
7375
root.classList.add('foo');
7476
component.getDefaultFoundation().adapter_.removeClass('foo');
7577
assert.isNotOk(root.classList.contains('foo'));
7678
});
7779

7880
test('#adapter.addInputClass adds a class to the input element', () => {
79-
const {root, component} = setupTest();
81+
const { root, component } = setupTest();
8082
const input = root.querySelector('.mdc-slider__input');
8183
component.getDefaultFoundation().adapter_.addInputClass('foo');
8284
assert.isOk(input.classList.contains('foo'));
8385
});
8486

8587
test('#adapter.removeInputClass removes a class from the input element', () => {
86-
const {root, component} = setupTest();
88+
const { root, component } = setupTest();
8789
const input = root.querySelector('.mdc-slider__input');
8890
input.classList.add('foo');
8991
component.getDefaultFoundation().adapter_.removeInputClass('foo');
9092
assert.isNotOk(input.classList.contains('foo'));
9193
});
9294

9395
test('#adapter.registerHandler adds an event handler on the input element', () => {
94-
const {root, component} = setupTest();
96+
const { root, component } = setupTest();
9597
const handler = td.func('fooHandler');
9698
component.getDefaultFoundation().adapter_.registerHandler('foo', handler);
9799
domEvents.emit(root.querySelector('.mdc-slider__input'), 'foo');
98100
td.verify(handler(td.matchers.anything()));
99101
});
100102

101103
test('#adapter.deregisterHandler removes an event handler from the input element', () => {
102-
const {root, component} = setupTest();
104+
const { root, component } = setupTest();
103105
const input = root.querySelector('.mdc-slider__input');
104106
const handler = td.func('fooHandler');
105107
input.addEventListener('foo', handler);
106108
component.getDefaultFoundation().adapter_.deregisterHandler('foo', handler);
107109
domEvents.emit(input, 'foo');
108-
td.verify(handler(td.matchers.anything()), {times: 0});
110+
td.verify(handler(td.matchers.anything()), { times: 0 });
109111
});
110112

111113
test('#adapter.registerRootHandler adds an event handler on the root element', () => {
112-
const {root, component} = setupTest();
114+
const { root, component } = setupTest();
113115
const handler = td.func('fooHandler');
114116
component.getDefaultFoundation().adapter_.registerRootHandler('foo', handler);
115117
domEvents.emit(root, 'foo');
116118
td.verify(handler(td.matchers.anything()));
117119
});
118120

119121
test('#adapter.deregisterRootHandler removes an event handler from the root element', () => {
120-
const {root, component} = setupTest();
122+
const { root, component } = setupTest();
121123
const handler = td.func('fooHandler');
122124
root.addEventListener('foo', handler);
123125
component.getDefaultFoundation().adapter_.deregisterRootHandler('foo', handler);
124126
domEvents.emit(root, 'foo');
125-
td.verify(handler(td.matchers.anything()), {times: 0});
127+
td.verify(handler(td.matchers.anything()), { times: 0 });
126128
});
127129

128130
test('#adapter.getNativeInput returns the component input element', () => {
129-
const {root, component} = setupTest();
130-
assert.equal(
131-
component.getDefaultFoundation().adapter_.getNativeInput(),
132-
root.querySelector('.mdc-slider__input')
133-
);
131+
const { root, component } = setupTest();
132+
assert.equal(component.getDefaultFoundation().adapter_.getNativeInput(), root.querySelector('.mdc-slider__input'));
134133
});
135134

136135
test('#adapter.setAttr sets an attribute to a certain value on the input element', () => {
137-
const {root, component} = setupTest();
136+
const { root, component } = setupTest();
138137
const input = root.querySelector('.mdc-slider__input');
139138
component.getDefaultFoundation().adapter_.setAttr('aria-valuenow', 'foo');
140139
assert.equal(input.getAttribute('aria-valuenow'), 'foo');
141140
});
142141

143142
test('adapter#setLowerStyle sets the given style propertyName to the given value', () => {
144-
const {component, root} = setupTest();
143+
const { component, root } = setupTest();
145144
const lower = root.querySelector('.mdc-slider__background-lower');
146145
component.getDefaultFoundation().adapter_.setLowerStyle('flex', '0.5 1 0%');
147146
assert.equal(lower.style.getPropertyValue('flex'), '0.5 1 0%');
148147
});
149148

150149
test('adapter#setUpperStyle sets the given style propertyName to the given value', () => {
151-
const {component, root} = setupTest();
150+
const { component, root } = setupTest();
152151
const upper = root.querySelector('.mdc-slider__background-upper');
153152
component.getDefaultFoundation().adapter_.setUpperStyle('flex', '0.5 1 0%');
154153
assert.equal(upper.style.getPropertyValue('flex'), '0.5 1 0%');
155154
});
156155

157156
test('#adapter.notifyChange broadcasts a "MDCSlider:change" custom event', () => {
158-
const {root, component} = setupTest();
157+
const { root, component } = setupTest();
159158
const handler = td.func('custom event handler');
160159
root.addEventListener('MDCSlider:change', handler);
161160
component.getDefaultFoundation().adapter_.notifyChange({});
162161
td.verify(handler(td.matchers.anything()));
163162
});
163+
164+
test('get/set value updates the value of the native checkbox element', () => {
165+
const { root, component } = setupTest();
166+
const cb = root.querySelector(strings.INPUT_SELECTOR);
167+
component.value = '59';
168+
assert.equal(cb.value, '59');
169+
assert.equal(component.value, cb.value);
170+
});

0 commit comments

Comments
 (0)