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

Commit 48bca5d

Browse files
committed
Making Fieldset double-linkable. Updating documentation + adding for Fieldset. Removing lodash as a dependency (only get and toPath are used now). Adding unit tests for Fieldset + deep resolves
1 parent fc1c83b commit 48bca5d

File tree

9 files changed

+111
-6
lines changed

9 files changed

+111
-6
lines changed

docs/api/Fieldset.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Fieldset Component
2+
3+
The `<Fieldset>` component is a way to contain related fields. This might not sound like much, but it's incredibly useful when creating **reusable groups of controls**. Here's an example:
4+
5+
```jsx
6+
// in render():
7+
<Form model="user">
8+
<Fieldset model=".address">
9+
<Control.text model=".city" />
10+
<Control.text model=".state" />
11+
<Control.text model=".zip" />
12+
</Fieldset>
13+
</Form>
14+
```
15+
16+
If you extract the `<Fieldset model=".address">` out into its own component, you can then reuse it inside any other `<Form>`:
17+
18+
```jsx
19+
const Address = () => (
20+
<Fieldset model=".address">
21+
<Control.text model=".city" />
22+
<Control.text model=".state" />
23+
<Control.text model=".zip" />
24+
</Fieldset>
25+
);
26+
27+
// in render():
28+
<Form model="user">
29+
<Address />
30+
</Form>
31+
32+
<Form model="admin">
33+
<Address />
34+
</Form>
35+
```
36+
37+
# Prop Types
38+
39+
## `model="..."` (required)
40+
_(String | Function)_: The string or [tracker](../guides/tracking) representing the model value of the entire form in the store.
41+
42+
You can also use [partial models](../guides/partial-models) for `<Control>`, `<Field>`, and `<Errors>` components inside of `<Fieldset>` - they will be resolved to the fieldset's model.
43+
44+
In addition, you can use a partial model for `<Fieldset>` itself - it will resolve to the parent `<Fieldset>` (yes, you can nest fieldsets) or `<Form>` models.
45+
46+
## `component={...}`
47+
_(Any)_ The `component` that the `<Fieldset>` should be rendered to (default: `"div"`).
48+
49+
- For React Native, the `View` component is used to render the fieldset, if you `import { Fieldset } from 'react-redux-form/native'`.

docs/api/Form.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ _(String | Function)_: The string representing the model value of the entire for
4747

4848
Typically, the `<Control>` (and/or `<Field>`) components nested inside `<Form>` would be _members_ of the form model; e.g. `user.email` and `user.password` are members of the `user` model.
4949

50-
You can also use [partial models](../guides/partial-models) for `<Control>`, `<Field>`, and `<Errors>` components inside of `<Form>` - they will be resolved to the form's model.
50+
You can also use [partial models](../guides/partial-models) for `<Control>`, `<Field>`, `<Fieldset>`, and `<Errors>` components inside of `<Form>` - they will be resolved to the form's model.
5151

5252
## `validators={{...}}`
5353
_(Object)_: An object representing the validators for the fields inside the form, where:

docs/guides/partial-models.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,20 @@ const AddressFields = () => (
5454
<AddressFields />
5555
</Form>
5656
```
57+
58+
## Deeply Resolved Models
59+
60+
With [`<Fieldset>`](../api/Fieldset), you can deeply resolve models:
61+
62+
```jsx
63+
// in render():
64+
<Form model="user">
65+
<Fieldset model=".address">
66+
<Control.text model=".city" />
67+
<Control.text model=".state" />
68+
<Control.text model=".zip" />
69+
</Fieldset>
70+
</Form>
71+
```
72+
73+
This makes it even easier to create reusable groups of controls.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@
9090
"dependencies": {
9191
"icepick": "^1.1.0",
9292
"invariant": "~2.2.1",
93-
"lodash": "^4.10.0"
93+
"lodash.get": "~4.4.2",
94+
"lodash.topath": "~4.5.2"
9495
},
9596
"peerDependencies": {
9697
"react": "^0.14.0 || ^15.0.0",

src/components/fieldset-component.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { Component, PropTypes } from 'react';
22
import { connect } from 'react-redux';
33
import getModel from '../utils/get-model';
44
import omit from '../utils/omit';
5+
import resolveModel from '../utils/resolve-model';
56

67
const propTypes = {
78
model: PropTypes.string.isRequired,
@@ -30,6 +31,8 @@ class Fieldset extends Component {
3031
}
3132
}
3233

34+
Fieldset.displayName = 'Fieldset';
35+
3336
Fieldset.childContextTypes = {
3437
model: PropTypes.any,
3538
};
@@ -48,4 +51,4 @@ function mapStateToProps(state, { model }) {
4851
};
4952
}
5053

51-
export default connect(mapStateToProps)(Fieldset);
54+
export default resolveModel(connect(mapStateToProps)(Fieldset));

src/utils/get.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import _get from 'lodash/get';
1+
import _get from 'lodash.get';
22
import endsWith from './ends-with';
33

44
export default function get(object, path, defaultValue) {

src/utils/path-starts-with.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import toPath from 'lodash/toPath';
1+
import toPath from 'lodash.toPath';
22

33
export default function pathStartsWith(pathString, subPathString) {
44
if (pathString === subPathString) return true;

src/utils/to-path.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import _toPath from 'lodash/toPath';
1+
import _toPath from 'lodash.toPath';
22
import endsWith from './ends-with';
33

44
export default function toPath(value) {

test/model-resolving-spec.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,39 @@ describe('model resolving', () => {
160160
assert.equal(errors[0].innerHTML, 'this is incorrect');
161161
});
162162
});
163+
164+
describe('deep resolves with <Fieldset>', () => {
165+
const deepInitialState = {
166+
foo: {
167+
field: 'field value',
168+
control: 'control value',
169+
},
170+
};
171+
172+
const deepStore = testCreateStore({
173+
test: modelReducer('test', deepInitialState),
174+
testForm: formReducer('test', deepInitialState),
175+
});
176+
177+
const app = testRender(
178+
<Form model="test">
179+
<Fieldset model=".foo">
180+
<Field model=".field">
181+
<input type="text" />
182+
</Field>
183+
<Control.text model=".control" />
184+
</Fieldset>
185+
</Form>, deepStore);
186+
187+
const [fieldInput, controlInput] = TestUtils
188+
.scryRenderedDOMComponentsWithTag(app, 'input');
189+
190+
it('deeply resolve a Field', () => {
191+
assert.equal(fieldInput.value, 'field value');
192+
});
193+
194+
it('deeply resolve a Control', () => {
195+
assert.equal(controlInput.value, 'control value');
196+
});
197+
});
163198
});

0 commit comments

Comments
 (0)