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

Commit 22d6a80

Browse files
committed
Merge branch 'master' of github.com:davidkpiano/react-redux-form
2 parents b19e111 + f4d2229 commit 22d6a80

File tree

9 files changed

+10921
-6122
lines changed

9 files changed

+10921
-6122
lines changed

package-lock.json

Lines changed: 10787 additions & 6100 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
"lodash.get": "~4.4.2",
9494
"lodash.topath": "~4.5.2",
9595
"prop-types": "^15.5.6",
96-
"shallow-compare": "1.2.2"
96+
"shallow-compare": "^1.2.1"
9797
},
9898
"peerDependencies": {
9999
"react": "^15.3.0 || ^16.0.0",

react-redux-form.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1081,7 +1081,7 @@ interface Actions {
10811081
* Can be dispatched to reset the validity and errors of any model at any time.
10821082
* @param model The model
10831083
*/
1084-
resetValidity: (model: string) => ActionThunk;
1084+
resetValidity: (model: string) => FieldAction;
10851085
/**
10861086
* Can be dispatched to reset the validity and errors of any model at any time.
10871087
* @param model The model

src/components/control-component.js

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ const propTypes = {
8888
component: PropTypes.any,
8989
dispatch: PropTypes.func,
9090
parser: PropTypes.func,
91+
formatter: PropTypes.func,
9192
ignore: PropTypes.oneOfType([
9293
PropTypes.arrayOf(PropTypes.string),
9394
PropTypes.string,
@@ -149,7 +150,7 @@ function createControlClass(s = defaultStrategy) {
149150
this.willValidate = false;
150151

151152
this.state = {
152-
viewValue: props.modelValue,
153+
viewValue: this.format(props.modelValue),
153154
};
154155
}
155156

@@ -360,7 +361,12 @@ function createControlClass(s = defaultStrategy) {
360361

361362
setViewValue(viewValue) {
362363
if (!this.props.isToggle) {
363-
this.setState({ viewValue: this.parse(viewValue) });
364+
if (this.props.formatter) {
365+
const parsedValue = this.parse(viewValue);
366+
this.setState({ viewValue: this.format(parsedValue) });
367+
} else {
368+
this.setState({ viewValue: this.parse(viewValue) });
369+
}
364370
}
365371
}
366372

@@ -403,15 +409,18 @@ function createControlClass(s = defaultStrategy) {
403409
return;
404410
}
405411
case 'validate':
412+
if (containsEvent(validateOn, 'change')) {
413+
this.validate({ clearIntents: intent });
414+
}
415+
return;
406416
case 'reset':
407-
if (intent.type === 'reset') {
408-
this.setViewValue(modelValue);
409-
if (this.handleUpdate.cancel) {
410-
this.handleUpdate.cancel();
411-
}
417+
this.setViewValue(modelValue);
418+
if (this.handleUpdate.cancel) {
419+
this.handleUpdate.cancel();
412420
}
421+
dispatch(actions.clearIntents(model, intent));
413422
if (containsEvent(validateOn, 'change')) {
414-
this.validate({ clearIntents: intent });
423+
this.validate({});
415424
}
416425
return;
417426

@@ -433,6 +442,12 @@ function createControlClass(s = defaultStrategy) {
433442
: value;
434443
}
435444

445+
format(value) {
446+
return this.props.formatter
447+
? this.props.formatter(value)
448+
: value;
449+
}
450+
436451
handleChange(event) {
437452
if (event && event.persist) event.persist();
438453

src/components/errors-component.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const propTypes = {
3131
// Provided props
3232
model: PropTypes.string.isRequired,
3333
messages: PropTypes.objectOf(PropTypes.oneOfType([
34-
PropTypes.string,
34+
PropTypes.node,
3535
PropTypes.func,
3636
PropTypes.bool,
3737
])),

src/components/field-component.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const fieldPropTypes = {
2929
PropTypes.string,
3030
]),
3131
parser: PropTypes.func,
32+
formatter: PropTypes.func,
3233
updateOn: PropTypes.oneOfType([
3334
PropTypes.arrayOf(PropTypes.string),
3435
PropTypes.string,
@@ -242,6 +243,7 @@ function createFieldClass(customControlPropsMap = {}, s = defaultStrategy) {
242243
updateOn: 'change',
243244
asyncValidateOn: 'blur',
244245
parser: identity,
246+
formatter: identity,
245247
changeAction: actions.change,
246248
dynamic: true,
247249
component: 'div',

test/control-component-spec.js

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,20 +1097,48 @@ Object.keys(testContexts).forEach((testKey) => {
10971097
test: modelReducer('test', initialState),
10981098
});
10991099

1100-
TestUtils.renderIntoDocument(
1101-
<Provider store={store}>
1102-
<Control.text
1103-
model="test.foo"
1104-
/>
1105-
</Provider>
1106-
);
1107-
11081100
it('should reset the control to the last loaded value', () => {
1101+
TestUtils.renderIntoDocument(
1102+
<Provider store={store}>
1103+
<Control.text
1104+
model="test.foo"
1105+
/>
1106+
</Provider>
1107+
);
1108+
11091109
store.dispatch(actions.load('test.foo', 'new foo'));
11101110
store.dispatch(actions.reset('test.foo'));
11111111

11121112
assert.equal(get(store.getState().test, 'foo'), 'new foo');
11131113
});
1114+
1115+
const onEvents = [
1116+
'change',
1117+
'focus',
1118+
'blur',
1119+
];
1120+
1121+
onEvents.forEach((updateOn) => {
1122+
onEvents.forEach((validateOn) => {
1123+
const condition = `updateOn="${updateOn}", validateOn="${validateOn}"`;
1124+
it(`should clear reset intent when ${condition}`, () => {
1125+
TestUtils.renderIntoDocument(
1126+
<Provider store={store}>
1127+
<Control.text
1128+
model="test.foo"
1129+
updateOn={updateOn}
1130+
validateOn={validateOn}
1131+
/>
1132+
</Provider>
1133+
);
1134+
1135+
store.dispatch(actions.reset('test.foo'));
1136+
const hasResetIntent = store.getState().testForm.foo.intents
1137+
.some(intent => intent.type === 'reset');
1138+
assert.equal(hasResetIntent, false, 'has no pending reset intents');
1139+
});
1140+
});
1141+
});
11141142
});
11151143

11161144
describe('deep initial value after reset', () => {

test/field-formatter-spec.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { assert } from 'chai';
2+
import React from 'react';
3+
import TestUtils from 'react-dom/test-utils';
4+
import { combineReducers, createStore } from 'redux';
5+
import { Provider } from 'react-redux';
6+
7+
import { modelReducer, Field, formReducer } from '../src';
8+
9+
describe('<Field formatter={...} />', () => {
10+
it('should format the initial value immediately', () => {
11+
const store = createStore(combineReducers({
12+
test: modelReducer('test', { foo: 'initial' }),
13+
testForm: formReducer('test', { foo: 'initial' }),
14+
}));
15+
16+
const formatValue = val => val.toUpperCase();
17+
18+
const field = TestUtils.renderIntoDocument(
19+
<Provider store={store}>
20+
<Field
21+
model="test.foo"
22+
formatter={formatValue}
23+
>
24+
<input type="text" />
25+
</Field>
26+
</Provider>
27+
);
28+
29+
const input = TestUtils.findRenderedDOMComponentWithTag(field, 'input');
30+
31+
assert.equal(input.value, 'INITIAL');
32+
33+
assert.equal(store.getState().test.foo, 'initial');
34+
});
35+
36+
it('should update the viewValue with only the data returned by formatter', () => {
37+
const initial = { foo: '0123456789' };
38+
const expected = '0123';
39+
const inputValue = '012345678912341268374612837';
40+
41+
const store = createStore(combineReducers({
42+
test: modelReducer('test', initial),
43+
testForm: formReducer('test', initial),
44+
}));
45+
46+
const formatValue = val => val.substring(0, 4);
47+
48+
const field = TestUtils.renderIntoDocument(
49+
<Provider store={store}>
50+
<Field
51+
model="test.foo"
52+
formatter={formatValue}
53+
>
54+
<input type="text" />
55+
</Field>
56+
</Provider>
57+
);
58+
59+
const input = TestUtils.findRenderedDOMComponentWithTag(field, 'input');
60+
input.value = inputValue;
61+
TestUtils.Simulate.change(input);
62+
63+
assert.equal(input.value, expected);
64+
65+
assert.equal(store.getState().test.foo, inputValue);
66+
});
67+
});

yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3816,9 +3816,9 @@ [email protected]:
38163816
version "2.2.6"
38173817
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba"
38183818

3819-
3820-
version "1.2.1"
3821-
resolved "https://registry.yarnpkg.com/shallow-compare/-/shallow-compare-1.2.1.tgz#6a42931a81f8ab52bfad229c14f1635e5488ba7a"
3819+
shallow-compare@^1.2.1:
3820+
version "1.2.2"
3821+
resolved "https://registry.yarnpkg.com/shallow-compare/-/shallow-compare-1.2.2.tgz#fa4794627bf455a47c4f56881d8a6132d581ffdb"
38223822

38233823
shelljs@^0.6.0:
38243824
version "0.6.1"

0 commit comments

Comments
 (0)