diff --git a/examples/range.js b/examples/range.js index ef4edb9..e97263d 100644 --- a/examples/range.js +++ b/examples/range.js @@ -16,14 +16,34 @@ const CustomizedRange = React.createClass({ value: [20, 40], }; }, - onChange: function(value) { + onSliderChange: function(value) { log(value); this.setState({ value: value, }); }, + onMinChange: function(e) { + this.setState({ + min: +e.target.value || 0, + }); + }, + onMaxChange: function(e) { + this.setState({ + max: +e.target.value || 100, + }); + }, render: function() { - return ; + return ( +
+ + +
+ + +

+ +
+ ); }, }); diff --git a/examples/slider.js b/examples/slider.js index c06528f..45a4dad 100644 --- a/examples/slider.js +++ b/examples/slider.js @@ -19,16 +19,38 @@ const CustomizedSlider = React.createClass({ getInitialState: function() { return { value: 50, + min: 0, + max: 100, }; }, - onChange: function(value) { + onSliderChange: function(value) { log(value); this.setState({ value: value, }); }, + onMinChange: function(e) { + this.setState({ + min: +e.target.value || 0, + }); + }, + onMaxChange: function(e) { + this.setState({ + max: +e.target.value || 100, + }); + }, render: function() { - return ; + return ( +
+ + +
+ + +

+ +
+ ); }, }); diff --git a/package.json b/package.json index 85232df..ca8ff4d 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ ], "dependencies": { "classnames": "^2.2.1", + "object-assign": "^4.0.1", "rc-tooltip": "3.x", "rc-util": "3.x" } diff --git a/src/Slider.jsx b/src/Slider.jsx index 5b6ed60..76cd574 100644 --- a/src/Slider.jsx +++ b/src/Slider.jsx @@ -1,6 +1,7 @@ import React from 'react'; import {Dom as DomUtils} from 'rc-util'; import classNames from 'classnames'; +import objectAssign from 'object-assign'; import Track from './Track'; import Handle from './Handle'; import Dots from './Dots'; @@ -66,18 +67,34 @@ class Slider extends React.Component { } componentWillReceiveProps(nextProps) { + if (!('value' in nextProps || 'min' in nextProps || 'max' in nextProps)) return; + + const {lowerBound, upperBound} = this.state; if (nextProps.range) { const value = nextProps.value; - if (value) { - this.setState({ - upperBound: value[1], - lowerBound: value[0], - }); - } - } else if ('value' in nextProps) { + const nextUpperBound = this.trimAlignValue(value[1], nextProps); + const nextLowerBound = this.trimAlignValue(value[0], nextProps); + if (nextLowerBound === lowerBound && nextUpperBound === upperBound) return; + this.setState({ - upperBound: nextProps.value, + upperBound: nextUpperBound, + lowerBound: nextLowerBound, }); + if (this.isValueOutOfBounds(upperBound, nextProps) || + this.isValueOutOfBounds(lowerBound, nextProps)) { + this.props.onChange([nextLowerBound, nextUpperBound]); + } + } else { + const nextValue = this.trimAlignValue(nextProps.value, nextProps); + if (nextValue === upperBound && lowerBound === nextProps.min) return; + + this.setState({ + upperBound: nextValue, + lowerBound: nextProps.min, + }); + if (this.isValueOutOfBounds(upperBound, nextProps)) { + this.props.onChange(nextValue); + } } } @@ -214,10 +231,14 @@ class Slider extends React.Component { return precision; } - trimAlignValue(v) { + isValueOutOfBounds(value, props) { + return value < props.min || value > props.max; + } + + trimAlignValue(v, nextProps) { const state = this.state || {}; const {handle, lowerBound, upperBound} = state; - const {marks, step, min, max} = this.props; + const {marks, step, min, max} = objectAssign({}, this.props, nextProps || {}); let val = v; if (val <= min) { diff --git a/tests/index.spec.js b/tests/index.spec.js index f37a55a..2f958f1 100644 --- a/tests/index.spec.js +++ b/tests/index.spec.js @@ -106,7 +106,7 @@ describe('rc-slider', function() { expect(ReactTestUtils.scryRenderedDOMComponentsWithClass(slider, 'rc-slider-mark-text')[1].innerHTML).to.be('30'); expect(ReactTestUtils.scryRenderedDOMComponentsWithClass(slider, 'rc-slider-mark-text')[2].innerHTML).to.be('100'); - const range = ReactDOM.render(, div); + const range = ReactDOM.render(, div); expect(ReactTestUtils.scryRenderedDOMComponentsWithClass(range, 'rc-slider-mark-text').length).to.be(3); });