Skip to content
This repository was archived by the owner on Aug 23, 2022. It is now read-only.

Commit 0fffccb

Browse files
committed
Removing redundant modelValue prop from <Field> and adding support for Immutable <Field> component. Fixes #319
1 parent 6d31d97 commit 0fffccb

File tree

4 files changed

+79
-6
lines changed

4 files changed

+79
-6
lines changed

src/components/control-component.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { sequenceEventActions } from '../utils/sequence';
1010
import actions from '../actions';
1111

1212
function mapStateToProps(state, props) {
13-
const { model, mapProps } = props;
13+
const { model, mapProps, getter = _get } = props;
1414

1515
if (!mapProps) return props;
1616

@@ -21,7 +21,7 @@ function mapStateToProps(state, props) {
2121

2222
return {
2323
model,
24-
modelValue: _get(state, modelString),
24+
modelValue: getter(state, modelString),
2525
fieldValue,
2626
};
2727
}
@@ -186,12 +186,14 @@ Control.propTypes = {
186186
component: PropTypes.any,
187187
dispatch: PropTypes.func,
188188
parser: PropTypes.func,
189-
componentMap: PropTypes.object,
189+
componentMap: PropTypes.object, // will be deprecated
190+
getter: PropTypes.func,
190191
};
191192

192193
Control.defaultProps = {
193194
changeAction: actions.change,
194195
updateOn: 'change',
196+
getter: _get,
195197
};
196198

197199
export default connect(mapStateToProps)(Control);

src/components/field-component.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ function mapStateToProps(state, { model }) {
2121

2222
return {
2323
model: modelString,
24-
modelValue: _get(state, modelString),
2524
};
2625
}
2726

@@ -160,7 +159,6 @@ function createFieldControlComponent(control, props, options) {
160159
return (
161160
<Control
162161
{...controlProps}
163-
modelValue={props.modelValue}
164162
control={control}
165163
controlProps={control.props}
166164
component={control.type}
@@ -243,7 +241,6 @@ function createFieldClass(customControlPropsMap = {}, defaultProps = {}) {
243241
PropTypes.func,
244242
PropTypes.object,
245243
]),
246-
modelValue: PropTypes.any,
247244
mapProps: PropTypes.func,
248245
componentMap: PropTypes.object,
249246
dispatch: PropTypes.func,

src/immutable/index.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { createModeler } from '../reducers/model-reducer';
22
import { createModelReducerEnhancer } from '../enhancers/modeled-enhancer';
3+
import { createFieldClass } from '../components/field-component';
4+
import toPath from '../utils/to-path';
35

46
function immutableGet(state, path, defaultValue) {
57
try {
@@ -19,6 +21,24 @@ function immutableSet(state, path, value) {
1921
}
2022
}
2123

24+
function immutableGetFromState(state, modelString) {
25+
const path = toPath(modelString);
26+
27+
return path.reduce((subState, subPath) => {
28+
// Current subState is immutable
29+
if ('get' in subState) {
30+
return subState.get(subPath);
31+
}
32+
33+
// Current subState is a plain object/array
34+
return subState[subPath];
35+
}, state);
36+
}
37+
38+
const ImmutableField = createFieldClass(undefined, {
39+
getter: immutableGetFromState,
40+
});
41+
2242
const modelReducer = createModeler(immutableGet, immutableSet);
2343
const modelReducerEnhancer = createModelReducerEnhancer(modelReducer);
2444

@@ -33,4 +53,5 @@ export {
3353
createModelReducer,
3454
modelReducer,
3555
modelReducerEnhancer as modeled,
56+
ImmutableField as Field,
3657
};
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React from 'react';
2+
import { assert } from 'chai';
3+
import Immutable from 'immutable';
4+
import { createStore, combineReducers, applyMiddleware } from 'redux';
5+
import { Provider } from 'react-redux';
6+
import thunk from 'redux-thunk';
7+
import TestUtils from 'react-addons-test-utils';
8+
9+
import { formReducer, actions } from '../src';
10+
import {
11+
modelReducer as immutableModelReducer,
12+
Field as ImmutableField,
13+
} from '../src/immutable';
14+
15+
describe('<Field> with Immutable.js', () => {
16+
const reducer = immutableModelReducer('test',
17+
Immutable.fromJS({ foo: 'bar' }));
18+
19+
const store = createStore(combineReducers({
20+
test: reducer,
21+
testForm: formReducer('test', { foo: 'bar' }),
22+
}), applyMiddleware(thunk));
23+
24+
const field = TestUtils.renderIntoDocument(
25+
<Provider store={store}>
26+
<ImmutableField model="test.foo">
27+
<input />
28+
</ImmutableField>
29+
</Provider>
30+
);
31+
32+
const input = TestUtils.findRenderedDOMComponentWithTag(field, 'input');
33+
34+
it('control should have the immutable model value', () => {
35+
assert.equal(input.value, 'bar');
36+
});
37+
38+
it('should be able to change the value', () => {
39+
input.value = 'new';
40+
41+
TestUtils.Simulate.change(input);
42+
43+
assert.equal(store.getState().test.get('foo'), 'new');
44+
assert.equal(input.value, 'new');
45+
});
46+
47+
it('should be able to externally change the value', () => {
48+
store.dispatch(actions.change('test.foo', 'external'));
49+
50+
assert.equal(store.getState().test.get('foo'), 'external');
51+
assert.equal(input.value, 'external');
52+
});
53+
});

0 commit comments

Comments
 (0)