Skip to content

Commit c1330ff

Browse files
committed
Add label formatter
1 parent e1da4fb commit c1330ff

File tree

6 files changed

+84
-4
lines changed

6 files changed

+84
-4
lines changed

example/js/App.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ class App extends React.Component {
5454
console.log(value);
5555
}
5656

57+
formatLabel(labelValue) {
58+
return labelValue.toFixed(2);
59+
}
60+
5761
render() {
5862
const defaultValue = 2;
5963
const defaultValue2 = {
@@ -74,6 +78,7 @@ class App extends React.Component {
7478
<InputRange
7579
maxValue={20}
7680
minValue={0}
81+
labelSuffix="kg"
7782
value={this.state.value4}
7883
onChange={this.handleValue4Change.bind(this)}
7984
onChangeComplete={this.handleChangeComplete.bind(this)}
@@ -82,6 +87,7 @@ class App extends React.Component {
8287
<InputRange
8388
maxValue={10}
8489
minValue={-10}
90+
formatLabel={this.formatLabel.bind(this)}
8591
value={this.state.value2}
8692
defaultValue={defaultValue}
8793
onChange={this.handleValue2Change.bind(this)}

scss/_InputRangeLabel.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
color: $InputRange-label-color;
33
font-family: $InputRange-fontFamily;
44
font-size: 0.8rem;
5+
white-space: nowrap;
56
}
67

78
.InputRange-label--min,

src/InputRange/InputRange.js

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ function renderSliders(inputRange) {
187187
ariaLabelledby={ inputRange.props.ariaLabelledby }
188188
ariaControls={ inputRange.props.ariaControls }
189189
classNames={ classNames }
190+
formatLabel={ inputRange.formatLabel }
190191
key={ key }
191192
maxValue={ maxValue }
192193
minValue={ minValue }
@@ -240,6 +241,7 @@ export default class InputRange extends React.Component {
240241

241242
// Auto-bind
242243
autobind([
244+
'formatLabel',
243245
'handleInteractionEnd',
244246
'handleInteractionStart',
245247
'handleKeyDown',
@@ -367,6 +369,21 @@ export default class InputRange extends React.Component {
367369
this.updateValue(key, value);
368370
}
369371

372+
/**
373+
* Format label
374+
* @param {number} labelValue - Label value
375+
* @return {string} Formatted label value
376+
*/
377+
formatLabel(labelValue) {
378+
const { formatLabel, labelPrefix, labelSuffix } = this.props;
379+
380+
if (formatLabel) {
381+
return formatLabel(labelValue, { labelPrefix, labelSuffix });
382+
}
383+
384+
return `${labelPrefix}${labelValue}${labelSuffix}`;
385+
}
386+
370387
/**
371388
* Handle any mousemove event received by the slider
372389
* @param {SyntheticEvent} event - User event
@@ -548,7 +565,8 @@ export default class InputRange extends React.Component {
548565
onTouchStart={ this.handleTouchStart }>
549566
<Label
550567
className={ classNames.labelMin }
551-
containerClassName={ classNames.labelContainer }>
568+
containerClassName={ classNames.labelContainer }
569+
formatLabel={ this.formatLabel }>
552570
{ this.props.minValue }
553571
</Label>
554572

@@ -563,7 +581,8 @@ export default class InputRange extends React.Component {
563581

564582
<Label
565583
className={ classNames.labelMax }
566-
containerClassName={ classNames.labelContainer }>
584+
containerClassName={ classNames.labelContainer }
585+
formatLabel={ this.formatLabel }>
567586
{ this.props.maxValue }
568587
</Label>
569588

@@ -581,6 +600,9 @@ export default class InputRange extends React.Component {
581600
* @property {Function} classNames
582601
* @property {Function} defaultValue
583602
* @property {Function} disabled
603+
* @property {Function} formatLabel
604+
* @property {Function} labelPrefix
605+
* @property {Function} labelSuffix
584606
* @property {Function} maxValue
585607
* @property {Function} minValue
586608
* @property {Function} name
@@ -595,6 +617,9 @@ InputRange.propTypes = {
595617
classNames: React.PropTypes.objectOf(React.PropTypes.string),
596618
defaultValue: maxMinValuePropType,
597619
disabled: React.PropTypes.bool,
620+
formatLabel: React.PropTypes.func,
621+
labelPrefix: React.PropTypes.string,
622+
labelSuffix: React.PropTypes.string,
598623
maxValue: maxMinValuePropType,
599624
minValue: maxMinValuePropType,
600625
name: React.PropTypes.string,
@@ -610,6 +635,8 @@ InputRange.propTypes = {
610635
* @property {Object.<string, string>} defaultClassNames
611636
* @property {Range|number} defaultValue
612637
* @property {boolean} disabled
638+
* @property {string} labelPrefix
639+
* @property {string} labelSuffix
613640
* @property {number} maxValue
614641
* @property {number} minValue
615642
* @property {number} step
@@ -619,6 +646,8 @@ InputRange.defaultProps = {
619646
classNames: defaultClassNames,
620647
defaultValue: 0,
621648
disabled: false,
649+
labelPrefix: '',
650+
labelSuffix: '',
622651
maxValue: 10,
623652
minValue: 0,
624653
step: 1,

src/InputRange/Label.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@ export default class Label extends React.Component {
1717
*/
1818
render() {
1919
const { className, containerClassName } = this.props;
20+
const labelValue = this.props.formatLabel ?
21+
this.props.formatLabel(this.props.children) :
22+
this.props.children;
2023

2124
return (
2225
<span className={ className }>
2326
<span className={ containerClassName }>
24-
{ this.props.children }
27+
{ labelValue }
2528
</span>
2629
</span>
2730
);
@@ -34,9 +37,11 @@ export default class Label extends React.Component {
3437
* @property {Function} children
3538
* @property {Function} className
3639
* @property {Function} containerClassName
40+
* @property {Function} formatLabel
3741
*/
3842
Label.propTypes = {
3943
children: React.PropTypes.node,
4044
className: React.PropTypes.string,
4145
containerClassName: React.PropTypes.string,
46+
formatLabel: React.PropTypes.func,
4247
};

src/InputRange/Slider.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ export default class Slider extends React.Component {
154154
style={ style }>
155155
<Label
156156
className={ classNames.labelValue }
157-
containerClassName={ classNames.labelContainer }>
157+
containerClassName={ classNames.labelContainer }
158+
formatLabel={ this.props.formatLabel }>
158159
{ this.props.value }
159160
</Label>
160161

@@ -184,6 +185,7 @@ export default class Slider extends React.Component {
184185
* @property {Function} ariaLabelledby
185186
* @property {Function} ariaControls
186187
* @property {Function} className
188+
* @property {Function} formatLabel
187189
* @property {Function} maxValue
188190
* @property {Function} minValue
189191
* @property {Function} onSliderKeyDown
@@ -196,6 +198,7 @@ Slider.propTypes = {
196198
ariaLabelledby: React.PropTypes.string,
197199
ariaControls: React.PropTypes.string,
198200
classNames: React.PropTypes.objectOf(React.PropTypes.string),
201+
formatLabel: React.PropTypes.func,
199202
maxValue: React.PropTypes.number,
200203
minValue: React.PropTypes.number,
201204
onSliderKeyDown: React.PropTypes.func.isRequired,

test/InputRange.spec.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,42 @@ describe('InputRange', () => {
179179
});
180180
});
181181

182+
describe('formatLabel', () => {
183+
it('should format label by prepending prefix label if it is provided', () => {
184+
inputRange = renderComponent(
185+
<InputRange labelPrefix="$" value={value} onChange={onChange} />
186+
);
187+
188+
const output = inputRange.formatLabel(5);
189+
190+
expect(output).toEqual('$5');
191+
});
192+
193+
it('should format label by appending suffix label if it is provided', () => {
194+
inputRange = renderComponent(
195+
<InputRange labelSuffix="kg" value={value} onChange={onChange} />
196+
);
197+
198+
const output = inputRange.formatLabel(5);
199+
200+
expect(output).toEqual('5kg');
201+
});
202+
203+
it('should format label by calling custom formatter if it provided', () => {
204+
function formatLabel(labelValue) {
205+
return `${labelValue} burgers`;
206+
}
207+
208+
inputRange = renderComponent(
209+
<InputRange formatLabel={formatLabel} value={value} onChange={onChange} />
210+
);
211+
212+
const output = inputRange.formatLabel(5);
213+
214+
expect(output).toEqual('5 burgers');
215+
});
216+
});
217+
182218
describe('handleSliderMouseMove', () => {
183219
let slider;
184220
let event;

0 commit comments

Comments
 (0)