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

Commit aaf0795

Browse files
committed
More refactoring. Adding value to changeAction for checkbox. Fixes #474
1 parent 335f196 commit aaf0795

File tree

6 files changed

+67
-27
lines changed

6 files changed

+67
-27
lines changed

src/actions/model-actions.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,23 @@ export function createModelActions(s = defaultStrategies) {
8585

8686
const toggle = createModifierAction((value) => !value, undefined, 1);
8787

88+
const check = (model, value) => (dispatch, getState) => {
89+
const modelValue = s.get(getState(), model);
90+
91+
if (isMulti(model)) {
92+
const valueWithItem = modelValue || s.array;
93+
const valueWithoutItem = (valueWithItem || s.array)
94+
.filter(item => item !== value);
95+
const multiValue = (s.length(valueWithoutItem) === s.length(valueWithItem))
96+
? s.push(valueWithItem, value)
97+
: valueWithoutItem;
98+
99+
dispatch(change(model, multiValue));
100+
} else {
101+
dispatch(change(model, !modelValue));
102+
}
103+
};
104+
88105
const filter = createModifierAction((value, iteratee) => value.filter(iteratee), s.array, 2);
89106

90107
const reset = (model) => ({
@@ -132,6 +149,7 @@ export function createModelActions(s = defaultStrategies) {
132149
xor,
133150
push,
134151
toggle,
152+
check,
135153
filter,
136154
reset,
137155
map,

src/components/control-component.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ function containsEvent(events, event) {
3939
return !!~events.indexOf(event);
4040
}
4141

42+
function getReadOnlyValue(props) {
43+
const { modelValue, controlProps } = props;
44+
45+
switch (controlProps.type) {
46+
case 'checkbox':
47+
return typeof controlProps.value !== 'undefined'
48+
? controlProps.value
49+
: !modelValue; // simple checkbox
50+
51+
case 'radio':
52+
default:
53+
return controlProps.value;
54+
}
55+
}
56+
57+
4258
const propTypes = {
4359
model: PropTypes.oneOfType([
4460
PropTypes.func,
@@ -227,7 +243,7 @@ function createControlClass(customControlPropsMap = {}, s = defaultStrategy) {
227243
changeAction = this.props.changeAction,
228244
} = this.getMappedProps();
229245
const value = isReadOnlyValue(controlProps)
230-
? controlProps.value
246+
? getReadOnlyValue(this.props)
231247
: event;
232248

233249
return changeAction(model, getValue(value));
@@ -681,8 +697,8 @@ function createControlClass(customControlPropsMap = {}, s = defaultStrategy) {
681697
mapProps={{
682698
...controlPropsMap.checkbox,
683699
...props.mapProps,
684-
changeAction: props.changeAction || controlPropsMap.checkbox.changeAction,
685700
}}
701+
changeAction={props.changeAction || s.actions.check}
686702
{...omit(props, 'mapProps')}
687703
/>
688704
);

src/components/field-component.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ function getControlType(control, props, options) {
9797
const defaultStrategy = {
9898
Control,
9999
getFieldFromState,
100+
actions,
100101
};
101102

102103
function createFieldClass(customControlPropsMap = {}, s = defaultStrategy) {
@@ -122,6 +123,13 @@ function createFieldClass(customControlPropsMap = {}, s = defaultStrategy) {
122123
},
123124
};
124125

126+
// TODO: refactor
127+
const defaultControlPropsMap = {
128+
checkbox: {
129+
changeAction: s.actions.check,
130+
},
131+
};
132+
125133
class Field extends Component {
126134
shouldComponentUpdate(nextProps) {
127135
const { dynamic } = this.props;
@@ -165,6 +173,7 @@ function createFieldClass(customControlPropsMap = {}, s = defaultStrategy) {
165173
controlProps: control.props,
166174
component: control.type,
167175
mapProps,
176+
...(defaultControlPropsMap[controlType] || {}),
168177
});
169178
}
170179

src/constants/control-props-map.js

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,7 @@ import isMulti from '../utils/is-multi';
22
import i from 'icepick';
33
import actions from '../actions';
44

5-
const defaultStrategies = {
6-
array: [],
7-
object: {},
8-
length: (val) => val.length,
9-
push: i.push,
10-
};
11-
12-
function createControlPropsMap(s = defaultStrategies) {
5+
function createControlPropsMap() {
136
function getTextValue(value) {
147
if (typeof value === 'string' || typeof value === 'number') {
158
return `${value}`;
@@ -47,22 +40,6 @@ function createControlPropsMap(s = defaultStrategies) {
4740
checked: (props) => (props.defaultChecked
4841
? props.checked
4942
: isChecked(props)),
50-
changeAction: (props) => (model) => {
51-
const { modelValue, value } = props;
52-
53-
if (isMulti(model)) {
54-
const valueWithItem = modelValue || s.array;
55-
const valueWithoutItem = (valueWithItem || s.array)
56-
.filter(item => item !== value);
57-
const multiValue = (s.length(valueWithoutItem) === s.length(valueWithItem))
58-
? s.push(valueWithItem, value)
59-
: valueWithoutItem;
60-
61-
return actions.change(model, multiValue);
62-
}
63-
64-
return actions.change(model, !modelValue);
65-
},
6643
onChange: ({ onChange }) => onChange,
6744
onBlur: ({ onBlur }) => onBlur,
6845
onFocus: ({ onFocus }) => onFocus,

src/immutable.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ const immutableActions = {
114114

115115
const immutableModelReducer = createModeler(immutableStrategy);
116116
const immutableModelReducerEnhancer = createModelReducerEnhancer(immutableModelReducer);
117-
const immutableControlPropsMap = createControlPropsMap(immutableStrategy);
117+
const immutableControlPropsMap = createControlPropsMap();
118118
const ImmutableControl = createControlClass(immutableControlPropsMap, {
119119
get: immutableGetFromState,
120120
getFieldFromState: immutableGetFieldFromState,
@@ -125,6 +125,7 @@ const ImmutableField = createFieldClass(immutableControlPropsMap, {
125125
getter: immutableGetFromState,
126126
getFieldFromState: immutableGetFieldFromState,
127127
changeAction: immutableModelActions.change,
128+
actions: immutableModelActions,
128129
});
129130
const ImmutableErrors = createErrorsClass(immutableStrategy);
130131
const ImmutableForm = createFormClass({

test/control-component-spec.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,25 @@ Object.keys(testContexts).forEach((testKey) => {
13071307

13081308
assert.isTrue(customChanged);
13091309
});
1310+
1311+
it('should provide the inverse of the model value (checkbox)', (done) => {
1312+
const field = TestUtils.renderIntoDocument(
1313+
<Provider store={store}>
1314+
<Control.checkbox
1315+
model="test.customChecked"
1316+
changeAction={(model, value) => {
1317+
assert.equal(model, 'test.customChecked');
1318+
assert.equal(value, true); // initial value is false
1319+
done();
1320+
}}
1321+
/>
1322+
</Provider>
1323+
);
1324+
1325+
const control = TestUtils.findRenderedDOMComponentWithTag(field, 'input');
1326+
1327+
TestUtils.Simulate.change(control);
1328+
});
13101329
});
13111330

13121331
describe('event handlers on control', () => {

0 commit comments

Comments
 (0)