Skip to content
Permalink
Browse files

feat: Add callback notifying the start of any interaction (#66)

  • Loading branch information...
oyeanuj authored and davidchin committed Mar 10, 2017
1 parent 343e655 commit 4ca6ea24108661d319b9fc169bd473b4ddc223a9
@@ -124,6 +124,10 @@ Set a name for your form component.

Whenever your user interacts with your component (i.e.: dragging a slider), this function gets called. Inside the function, you should assign the new value to your component.

#### onChangeStart: (value: number | Range): void

Whenever your user starts interacting with your component (i.e.: `onMouseDown`, or `onTouchStart`), this function gets called.

#### onChangeComplete: (value: number | Range): void

Every mouse / touch event can trigger multiple updates, therefore causing `onChange` callback to fire multiple times. On the other hand, `onChangeComplete` callback only gets called when the user stops dragging.
@@ -42,6 +42,7 @@ export default class ExampleApp extends React.Component {
formatLabel={value => value.toFixed(2)}
value={this.state.value3}
onChange={value => this.setState({ value3: value })}
onChangeStart={value => console.log('onChangeStart with value =', value)}
onChangeComplete={value => console.log(value)} />

<InputRange
@@ -28,6 +28,7 @@ declare interface InputRangeProps {
minValue?: number;
name?: string;
onChange: (value: Range | number) => void;
onChangeStart?: (value: Range | number) => void;
onChangeComplete?: (value: Range | number) => void;
step?: number;
value: Range | number;
@@ -30,6 +30,7 @@ export default class InputRange extends React.Component {
maxValue: rangePropType,
minValue: rangePropType,
name: React.PropTypes.string,
onChangeStart: React.PropTypes.func,
onChange: React.PropTypes.func.isRequired,
onChangeComplete: React.PropTypes.func,
step: React.PropTypes.number,
@@ -64,6 +65,7 @@ export default class InputRange extends React.Component {
* @param {string} [props.name]
* @param {string} props.onChange
* @param {Function} [props.onChangeComplete]
* @param {Function} [props.onChangeStart]
* @param {number} [props.step = 1]
* @param {number|Range} props.value
*/
@@ -410,11 +412,13 @@ export default class InputRange extends React.Component {
*/
@autobind
handleInteractionStart() {
if (!this.props.onChangeComplete || isDefined(this.startValue)) {
return;
if (this.props.onChangeStart) {
this.props.onChangeStart(this.props.value);
}

this.startValue = this.props.value;
if (this.props.onChangeComplete && !isDefined(this.startValue)) {
this.startValue = this.props.value;
}
}

/**
@@ -255,6 +255,30 @@ describe('InputRange', () => {
component.detach();
});

it('notifies the parent component when dragging starts', () => {
const onChange = jasmine.createSpy('onChange').and.callFake(value => component.setProps({ value }));
const onChangeStart = jasmine.createSpy('onChangeStart');
const jsx = (
<InputRange
maxValue={20}
minValue={0}
value={{ min: 2, max: 10 }}
onChange={value => component.setProps({ value })}
onChangeStart={onChangeStart}
/>
);
const component = mount(jsx, { attachTo: container });
const slider = component.find(`Slider [onMouseDown]`).first();

slider.simulate('mouseDown', { clientX: 50, clientY: 50 });
document.dispatchEvent(new MouseEvent('mousemove', { clientX: 100, clientY: 50 }));
document.dispatchEvent(new MouseEvent('mousemove', { clientX: 150, clientY: 50 }));
document.dispatchEvent(new MouseEvent('mouseup', { clientX: 150, clientY: 50 }));
expect(onChangeStart.calls.count()).toEqual(1);

component.detach();
});

it('notifies the parent component when dragging stops', () => {
const onChange = jasmine.createSpy('onChange').and.callFake(value => component.setProps({ value }));
const onChangeComplete = jasmine.createSpy('onChangeComplete');

0 comments on commit 4ca6ea2

Please sign in to comment.
You can’t perform that action at this time.