diff --git a/dist/components/Field.js b/dist/components/Field.js index 6875ffc..c940da7 100644 --- a/dist/components/Field.js +++ b/dist/components/Field.js @@ -51,7 +51,11 @@ var Field = function (_React$Component) { _createClass(Field, [{ key: 'componentWillUpdate', value: function componentWillUpdate(nextProps) { - if (nextProps.value !== this.props.value && nextProps.value !== this.state.value) { + if (nextProps.passedValue !== this.props.passedValue) { + this.cancelBroadcast(); + this.setState({ value: nextProps.passedValue }); + this.finalValue = nextProps.passedValue; + } else if (nextProps.value !== this.props.value && nextProps.value !== this.state.value) { this.cancelBroadcast(); this.setState({ value: nextProps.value }); this.finalValue = nextProps.value; @@ -65,6 +69,7 @@ var Field = function (_React$Component) { }, { key: 'shouldComponentUpdate', value: function shouldComponentUpdate(nextProps) { + if (nextProps.passedValue !== this.props.passedValue) return true; if (nextProps.value !== this.state.value) return true; if (this.state.value !== this.finalValue) return true; if (this.props.match !== nextProps.match) return true; @@ -151,6 +156,7 @@ var Field = function (_React$Component) { Field.propTypes = { value: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.string, _react2.default.PropTypes.number]), + passedValue: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.string, _react2.default.PropTypes.number]), name: _react2.default.PropTypes.string, onChange: _react2.default.PropTypes.func, onFocus: _react2.default.PropTypes.func, @@ -163,6 +169,7 @@ Field.propTypes = { Field.defaultProps = { value: '', + passedValue: '', name: '', onChange: undefined, onFocus: undefined, diff --git a/dist/helpers/utilities.js b/dist/helpers/utilities.js index 6ec1d2a..d8e6cea 100644 --- a/dist/helpers/utilities.js +++ b/dist/helpers/utilities.js @@ -119,7 +119,11 @@ function getValuesOf() { function makeFieldProps(child, onChange, state) { if (typeof child.type === 'function' && child.type.name === 'Field') { var name = child.props.name; - return { name: name, onChange: onChange, key: name, value: state[name] ? state[name].value : null }; + var props = { name: name, onChange: onChange, key: name, value: state[name] ? state[name].value : null }; + + if (child.props.value !== undefined) props.passedValue = child.props.value; + + return props; } return null; } diff --git a/readme.md b/readme.md index 1e72dad..2ca58cd 100644 --- a/readme.md +++ b/readme.md @@ -196,7 +196,7 @@ The `Field` component will behave as follows with respect to its children: #### `props.value = value` > @param {String} [value=''] - The value of the wrapped input component. - This property is used to control the value of the wrapped input component. + This property is used to control the value of the wrapped input component. If set on the field, this value will be used everytime it is detected as a new (changed) value. This is useful in cases where you need to programmatically populate the field's value (but still allow the input to be edited). #### `props.type = type` > @param {String} [type='text'] - The input type of the wrapped input element. diff --git a/src/components/Field.jsx b/src/components/Field.jsx index de0922a..2f44b22 100644 --- a/src/components/Field.jsx +++ b/src/components/Field.jsx @@ -29,7 +29,11 @@ const Field = class extends React.Component { } componentWillUpdate(nextProps) { - if ((nextProps.value !== this.props.value) && (nextProps.value !== this.state.value)) { + if (nextProps.passedValue !== this.props.passedValue) { + this.cancelBroadcast(); + this.setState({ value: nextProps.passedValue }); + this.finalValue = nextProps.passedValue; + } else if (nextProps.value !== this.props.value && nextProps.value !== this.state.value) { this.cancelBroadcast(); this.setState({ value: nextProps.value }); this.finalValue = nextProps.value; @@ -42,6 +46,7 @@ const Field = class extends React.Component { } shouldComponentUpdate(nextProps) { + if (nextProps.passedValue !== this.props.passedValue) return true; if (nextProps.value !== this.state.value) return true; if (this.state.value !== this.finalValue) return true; if (this.props.match !== nextProps.match) return true; @@ -115,6 +120,7 @@ const Field = class extends React.Component { Field.propTypes = { value: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]), + passedValue: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]), name: React.PropTypes.string, onChange: React.PropTypes.func, onFocus: React.PropTypes.func, @@ -131,6 +137,7 @@ Field.propTypes = { Field.defaultProps = { value: '', + passedValue: '', name: '', onChange: undefined, onFocus: undefined, diff --git a/src/helpers/utilities.jsx b/src/helpers/utilities.jsx index 3557725..28dc85a 100644 --- a/src/helpers/utilities.jsx +++ b/src/helpers/utilities.jsx @@ -70,7 +70,11 @@ export function getValuesOf(obj = {}) { export function makeFieldProps(child, onChange, state) { if (typeof child.type === 'function' && child.type.name === 'Field') { const name = child.props.name; - return { name, onChange, key: name, value: state[name] ? state[name].value : null }; + const props = { name, onChange, key: name, value: state[name] ? state[name].value : null }; + + if (child.props.value !== undefined) props.passedValue = child.props.value; + + return props; } return null; } diff --git a/tests/components/Form.spec.js b/tests/components/Form.spec.js index 206fa3f..79cf905 100644 --- a/tests/components/Form.spec.js +++ b/tests/components/Form.spec.js @@ -145,4 +145,35 @@ describe('
Higher-Order-Component', () => { Form.prototype.reset.restore(); }); }); + + describe('Passes down a value prop that changed', () => { + let wrapper; + let fieldComponent; + const cache = { value: 'firstValue' }; + const retrieveCacheValue = () => cache.value; + const FieldWithValue = () =>