Skip to content
This repository was archived by the owner on May 12, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion dist/components/Field.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -163,6 +169,7 @@ Field.propTypes = {

Field.defaultProps = {
value: '',
passedValue: '',
name: '',
onChange: undefined,
onFocus: undefined,
Expand Down
6 changes: 5 additions & 1 deletion dist/helpers/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
9 changes: 8 additions & 1 deletion src/components/Field.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -131,6 +137,7 @@ Field.propTypes = {

Field.defaultProps = {
value: '',
passedValue: '',
name: '',
onChange: undefined,
onFocus: undefined,
Expand Down
6 changes: 5 additions & 1 deletion src/helpers/utilities.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
31 changes: 31 additions & 0 deletions tests/components/Form.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,35 @@ describe('<Form /> 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 = () => <Field name="nameField" value={retrieveCacheValue()} />;

before('Assemble a custom input element', () => {
wrapper = mount(
<Form>
{FieldWithValue()}
</Form>);
fieldComponent = wrapper.find(Field);
});

it('Should update its value when passed a new value prop', () => {
expect(fieldComponent.props()).to.have.property('name', 'nameField');
expect(fieldComponent.props()).to.have.property('value', 'firstValue');
expect(fieldComponent.props()).to.have.property('passedValue', 'firstValue');

// Update the cache's value;
cache.value = 'secondValue';
wrapper.setProps({ children: FieldWithValue() });

expect(fieldComponent.props()).to.have.property('name', 'nameField');
expect(fieldComponent.props()).to.have.property('value', 'firstValue');
expect(fieldComponent.props()).to.have.property('passedValue', 'secondValue');
expect(wrapper.state().nameField).to.eql({ value: 'firstValue', valid: false, pristine: true });
});
});
});