Skip to content

Commit 9f1d67d

Browse files
committed
initial commit
0 parents  commit 9f1d67d

File tree

6 files changed

+241
-0
lines changed

6 files changed

+241
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
bower_components

.npmignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
bower_components
3+
bower.json

README.md

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# [React](http://facebook.github.io/react/)-checkbox-group
2+
## Heavily inspired from https://github.com/chenglou/react-radio-group
3+
4+
This is your average checkbox group:
5+
6+
```html
7+
<form>
8+
<input type="checkbox" name="fruit" value="apple" />Apple
9+
<input type="checkbox" name="fruit" value="orange" />Orange
10+
<input type="checkbox" name="fruit" value="watermelon" />Watermelon
11+
</form>
12+
```
13+
14+
Repetitive, hard to manipulate and easily desynchronized.
15+
Lift up `name`, give the group an initial checked values array, and optionally remove the form tag:
16+
17+
```html
18+
<CheckboxGroup name="fruit" value={['apple','watermelon']}>
19+
<input type="checkbox" value="apple" />Apple
20+
<input type="checkbox" value="orange" />Orange
21+
<input type="checkbox" value="watermelon" />Watermelon
22+
</CheckboxGroup>
23+
```
24+
25+
Listen for changes, get the new value as intuitively as possible:
26+
27+
```html
28+
<CheckboxGroup name="fruit" value={['apple','watermelon']} ref="fruitsGroup" onChange={this.handleChange}>
29+
// further...
30+
31+
this.refs.fruitsGroup.getCheckedValues(); // => whatever's currently checked
32+
```
33+
34+
That's it for the API! See below for a complete example.
35+
36+
## Install
37+
38+
```sh
39+
bower install react-checkbox-group
40+
or
41+
npm install react-checkbox-group
42+
```
43+
44+
Simply require it to use it:
45+
46+
```javascript
47+
var CheckboxGroup = require('react-checkbox-group');
48+
```
49+
50+
## Example
51+
52+
```html
53+
/**
54+
* @jsx React.DOM
55+
*/
56+
var Demo = React.createClass({
57+
getInitialState: function() {
58+
return {value: ['apple','watermelon']};
59+
},
60+
61+
componentDidMount: function() {
62+
// Add orange and remove watermelon after 1 second
63+
setTimeout(function() {
64+
this.setState({value: ['apple','orange']});
65+
}.bind(this), 1000);
66+
},
67+
68+
render: function() {
69+
// the checkboxes can be arbitrarily deep. They will always be fetched and
70+
// attached the `name` attribute correctly. `value` is optional
71+
return (
72+
<CheckboxGroup
73+
name="fruits"
74+
value={this.state.value}
75+
ref="fruitsGroup"
76+
onChange={this.handleChange}
77+
>
78+
<div>
79+
<label>
80+
<input type="checkbox" value="apple"/>Apple
81+
</label>
82+
<label>
83+
<input type="checkbox" value="orange"/>Orange
84+
</label>
85+
<label>
86+
<input type="checkbox" value="watermelon"/>Watermelon
87+
</label>
88+
</div>
89+
</CheckboxGroup>
90+
);
91+
},
92+
93+
handleChange: function() {
94+
// will return the currently selected checkbox values as an array, possibly empty
95+
var selectedFruits = this.refs.fruitsGroup.getCheckedValues();
96+
}
97+
});
98+
99+
React.renderComponent(<Demo/>, document.body);
100+
```
101+
102+
## License
103+
104+
MIT.

bower.json

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "react-checkbox-group",
3+
"version": "0.1.4",
4+
"author": "Ziad Saab <[email protected]>",
5+
"description": "Sensible checkbox groups manipulation for DOM.",
6+
"main": "react-checkbox-group.jsx",
7+
"ignore": [
8+
"**/.*",
9+
"node_modules",
10+
"bower_components",
11+
"package.json"
12+
],
13+
"keywords": [
14+
"facebook",
15+
"react",
16+
"checkbox",
17+
"group",
18+
"dom",
19+
"input"
20+
],
21+
"dependencies": {
22+
"react": "~0.11.1"
23+
},
24+
"license": "MIT"
25+
}

package.json

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "react-checkbox-group",
3+
"version": "0.1.4",
4+
"description": "Sensible checkbox groups manipulation for DOM.",
5+
"main": "react-checkbox-group.jsx",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/ziad-saab/react-checkbox-group.git"
12+
},
13+
"keywords": [
14+
"facebook",
15+
"react",
16+
"checkbox",
17+
"group",
18+
"dom",
19+
"input"
20+
],
21+
"author": "Ziad Saab <[email protected]>",
22+
"license": "MIT",
23+
"bugs": {
24+
"url": "https://github.com/ziad-saab/react-checkbox-group/issues"
25+
},
26+
"homepage": "https://github.com/ziad-saab/react-checkbox-group",
27+
"dependencies": {
28+
"react": "~0.11.1"
29+
}
30+
}

react-checkbox-group.jsx

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* @jsx React.DOM
3+
*/
4+
var React = require('react');
5+
6+
var CheckboxGroup = module.exports = React.createClass({
7+
getInitialState: function() {
8+
return {defaultValue: this.props.defaultValue || []};
9+
},
10+
11+
componentDidMount: function() {
12+
this.setCheckboxNames();
13+
this.setCheckedBoxes();
14+
},
15+
16+
componentDidUpdate: function() {
17+
this.setCheckboxNames();
18+
this.setCheckedBoxes();
19+
},
20+
21+
render: function() {
22+
return this.transferPropsTo(
23+
<div onChange={this.props.onChange}>
24+
{this.props.children}
25+
</div>
26+
);
27+
},
28+
29+
setCheckboxNames: function() {
30+
// stay DRY and don't put the same `name` on all checkboxes manually. Put it on
31+
// the tag and it'll be done here
32+
var $checkboxes = this.getCheckboxes();
33+
for (var i = 0, length = $checkboxes.length; i < length; i++) {
34+
$checkboxes[i].setAttribute('name', this.props.name);
35+
}
36+
},
37+
38+
getCheckboxes: function() {
39+
return this.getDOMNode().querySelectorAll('input[type="checkbox"]');
40+
},
41+
42+
setCheckedBoxes: function() {
43+
var $checkboxes = this.getCheckboxes();
44+
// if `value` is passed from parent, always use that value. This is similar
45+
// to React's controlled component. If `defaultValue` is used instead,
46+
// subsequent updates to defaultValue are ignored. Note: when `defaultValue`
47+
// and `value` are both passed, the latter takes precedence, just like in
48+
// a controlled component
49+
var destinationValue = this.props.value != null
50+
? this.props.value
51+
: this.state.defaultValue;
52+
53+
for (var i = 0, length = $checkboxes.length; i < length; i++) {
54+
var $checkbox = $checkboxes[i];
55+
56+
// intentionally use implicit conversion for those who accidentally used,
57+
// say, `valueToChange` of 1 (integer) to compare it with `value` of "1"
58+
// (auto conversion to valid html value from React)
59+
if (destinationValue.indexOf($checkbox.value) >= 0) {
60+
$checkbox.checked = true;
61+
}
62+
}
63+
},
64+
65+
getCheckedValues: function() {
66+
var $checkboxes = this.getCheckboxes();
67+
68+
var checked = [];
69+
for (var i = 0, length = $checkboxes.length; i < length; i++) {
70+
if ($checkboxes[i].checked) {
71+
checked.push($checkboxes[i].value);
72+
}
73+
}
74+
75+
return checked;
76+
}
77+
});

0 commit comments

Comments
 (0)