Skip to content

Commit a6fe055

Browse files
author
Vlad Balin
committed
moved code from NestedReact
0 parents  commit a6fe055

File tree

3 files changed

+431
-0
lines changed

3 files changed

+431
-0
lines changed

.gitignore

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
### JetBrains template
2+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
3+
4+
*.iml
5+
6+
## Directory-based project format:
7+
.idea/
8+
# if you remove the above rule, at least ignore the following:
9+
10+
# User-specific stuff:
11+
# .idea/workspace.xml
12+
# .idea/tasks.xml
13+
# .idea/dictionaries
14+
15+
# Sensitive or high-churn files:
16+
# .idea/dataSources.ids
17+
# .idea/dataSources.xml
18+
# .idea/sqlDataSources.xml
19+
# .idea/dynamic.xml
20+
# .idea/uiDesigner.xml
21+
22+
# Gradle:
23+
# .idea/gradle.xml
24+
# .idea/libraries
25+
26+
# Mongo Explorer plugin:
27+
# .idea/mongoSettings.xml
28+
29+
## File-based project format:
30+
*.ipr
31+
*.iws
32+
33+
## Plugin-specific files:
34+
35+
# IntelliJ
36+
/out/
37+
38+
# mpeltonen/sbt-idea plugin
39+
.idea_modules/
40+
41+
# JIRA plugin
42+
atlassian-ide-plugin.xml
43+
44+
# Crashlytics plugin (for Android Studio and IntelliJ)
45+
com_crashlytics_export_strings.xml
46+
crashlytics.properties
47+
crashlytics-build.properties
48+
49+
# Created by .ignore support plugin (hsz.mobi)

README.md

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
# Features
2+
3+
- Create links to state's attributes
4+
var nameLink = Link.state( this, 'name' );
5+
- Create links to nested arrays and objects
6+
var phonebookLink = Link.state( this, 'phonebook' );
7+
8+
var list = phonebookLink.map( itemLink => (
9+
<div>
10+
<input valueLink={ itemLink.at( 'name' ) } />
11+
</div>
12+
));
13+
14+
-
15+
16+
17+
# Installation
18+
19+
`npm install valuelink`
20+
21+
# Data binding examples
22+
23+
Here are the set of examples for typical `nestedreact` data binding use cases.
24+
25+
Each section contains custom databound component, model definitions, and usage examples.
26+
27+
Somewhere at the top level component(s) there must be the declaration linking model updates to UI. Either models must be (nested) members of some component's state (which will update UI even in case of deep changes), or you may link component updates to changes of models and collections passed in props. In the last case, you will need to add following line to top or middle-level component definition:
28+
29+
```
30+
listenToProps : 'myModel myCollection'
31+
```
32+
33+
It's generally advised to keep stateful components at the top level, and use `listenToProps` in the middle level for optimization purposes if you want local updates. Keep you bottom-level components pure, and try to do the same for the most of your middle level (`listenToProps` used wisely won't hurt). For further information on this topic consult the top-level guide.
34+
35+
## Checkboxes
36+
37+
Standard `<input/>` will work. Custom Checkbox component might be implemented like this:
38+
39+
```javascript
40+
const Checkbox = ({ className = 'checkbox', checkedLink }) => (
41+
<div className={ className + ( checkedLink.value ? ' selected' : '' ) }
42+
onClick = { checkedLink.update( x => !x ) }
43+
/>
44+
);
45+
```
46+
47+
Examples will assume working with custom Checkbox.
48+
49+
### Binding to boolean model attributes
50+
51+
```javascript
52+
import { Model } from 'nestedtypes'
53+
54+
const MyModel = Model
55+
.defaults({
56+
option1 : true,
57+
option2 : false
58+
});
59+
60+
const CheckboxGroup = ({ model /* instanceof MyModel */ }) => (
61+
<div>
62+
<div>
63+
<Checkbox checkedLink={ model.getLink( 'option1' ) } />
64+
Option 1
65+
</div>
66+
<div>
67+
<Checkbox checkedLink={ model.getLink( 'option2' ) } />
68+
Option 2
69+
</div>
70+
</div>
71+
);
72+
```
73+
74+
### Binding to array of selected options
75+
76+
```javascript
77+
import { Model } from 'nestedtypes'
78+
79+
const MyModel = Model
80+
.defaults({
81+
options : [ 'option1' ]
82+
});
83+
84+
const CheckboxGroup = ({ model /* instanceof MyModel */ }) => {
85+
const link = model.getLink( 'options' );
86+
87+
return (
88+
<div>
89+
<div>
90+
<Checkbox checkedLink={ link.contains( 'option1' ) } />
91+
Option 1
92+
</div>
93+
<div>
94+
<Checkbox checkedLink={ link.contains( 'option2' ) } />
95+
Option 2
96+
</div>
97+
</div>
98+
);
99+
};
100+
```
101+
102+
### Binding to collection of selected models
103+
104+
```javascript
105+
import { Model } from 'nestedtypes'
106+
107+
const MyModel = Model
108+
.defaults({
109+
all : Some.Collection,
110+
selected : Collection.subsetOf( 'all' )
111+
});
112+
113+
const CheckboxGroup = ({ model /* instanceof MyModel */ }) => {
114+
const { all, selected } = model;
115+
116+
return (
117+
<div>
118+
{ all.map( model => (
119+
<div>
120+
<Checkbox checkedLink={ selected.getLink( model ) } />
121+
{ model.displayName }
122+
</div>
123+
))}
124+
</div>
125+
);
126+
};
127+
```
128+
129+
## Radio Groups
130+
131+
For the radio groups you will need custom Radio component. It's very similar to custom Checkbox one,
132+
with one difference in click handler:
133+
134+
```javascript
135+
const Radio = ({ className = 'radio', checkedLink }) => (
136+
<div className={ className + ( checkedLink.value ? ' selected' : '' ) }
137+
onClick = { checkedLink.update( () => true ) }
138+
/>
139+
);
140+
```
141+
142+
In this example, we bind radio to string values. It's not required for them to be strings.
143+
144+
```javascript
145+
import { Model } from 'nestedtypes'
146+
147+
const MyModel = Model
148+
.defaults({
149+
option : 'option1'
150+
});
151+
152+
const RadioGroup = ({ model /* instanceof MyModel */ }) => {
153+
const link = model.getLink( 'option' );
154+
155+
return (
156+
<div>
157+
<div>
158+
<Radio checkedLink={ link.equals( 'option1' ) } />
159+
Option 1
160+
</div>
161+
<div>
162+
<Radio checkedLink={ link.equals( 'option2' ) } />
163+
Option 2
164+
</div>
165+
</div>
166+
);
167+
};
168+
```
169+
170+
## Input fields
171+
172+
Standard `<input>` will work. You may implement custom input controls to handle complex scenarios
173+
with validation and appearance.
174+
175+
```javascript
176+
const Input = ({ valueLink, ...props }) => (
177+
<div className='wrapping'
178+
<input {...props} value={ valueLink.value } onChange={ e => valueLink.set( e.target.value ) }/>
179+
</div>
180+
);
181+
```
182+
183+
### Binding to model attributes
184+
185+
```javascript
186+
import { Model } from 'nestedtypes'
187+
188+
const MyModel = Model
189+
.defaults({
190+
number : 0,
191+
string : ''
192+
});
193+
194+
const InputGroup = ({ model /* instanceof MyModel */ }) => (
195+
<div>
196+
<label>
197+
Number:
198+
<input type='number' valueLink={ model.getLink( 'number' ) } />
199+
</label>
200+
<label>
201+
String:
202+
<input valueLink={ model.getLink( 'string' ) } />
203+
</label>
204+
</div>
205+
);
206+
};
207+
```
208+
209+
### Binding to an array of strings
210+
211+
The same technique may be used to bind to an array or hash of strings. First, take a link to this
212+
attribute. Next, use `link.map` method to iterate through elements links created for you.
213+
214+
`link.map` will internally execute `link.at( key )` method to create a link to the plain object or array element.
215+
These methods may be used manually to create binding for the structures of any particular depth and complexity.
216+
217+
However, for the JS data with known structure it's recommended to wrap them in models.
218+
219+
```javascript
220+
import { Model } from 'nestedtypes'
221+
222+
const MyModel = Model
223+
.defaults({
224+
strings : [ 'first', 'second' ]
225+
});
226+
227+
const InputGroup = ({ model /* instanceof MyModel */ }) => (
228+
<div>
229+
{ model.getLink( 'strings' ).map( strLink => (
230+
<div>
231+
<input type='number' valueLink={ strLink } />
232+
</div>
233+
)) }
234+
</div>
235+
);
236+
};
237+
```

0 commit comments

Comments
 (0)