forked from ziad-saab/react-checkbox-group
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreact-checkbox-group.jsx
110 lines (92 loc) · 2.82 KB
/
react-checkbox-group.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import React, { Component } from 'react'
import PropTypes from 'prop-types'
export class Checkbox extends Component {
displayName: 'Checkbox'
static contextTypes = {
checkboxGroup: PropTypes.object.isRequired
}
componentWillMount() {
if (!(this.context && this.context.checkboxGroup)) {
throw new Error('The `Checkbox` component must be used as a child of `CheckboxGroup`.')
}
}
render() {
const { name, checkedValues, onChange } = this.context.checkboxGroup
const optional = {}
if (checkedValues) {
optional.checked = checkedValues.indexOf(this.props.value) >= 0
}
if (typeof onChange === 'function') {
optional.onChange = onChange.bind(null, this.props.value)
}
return <input {...this.props} type="checkbox" name={name} disabled={this.props.disabled} {...optional} />
}
}
export class CheckboxGroup extends Component {
displayName: 'CheckboxGroup'
static childContextTypes = {
checkboxGroup: PropTypes.object.isRequired
}
static propTypes = {
name: PropTypes.string,
defaultValue: PropTypes.array,
selectedValue: PropTypes.array,
onChange: PropTypes.func,
children: PropTypes.node.isRequired,
Component: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.object])
}
static defaultProps = {
Component: 'div'
}
constructor(props) {
super(props)
this._isControlledComponent = this._isControlledComponent.bind(this)
this._onCheckboxChange = this._onCheckboxChange.bind(this)
this.getChildContext = this.getChildContext.bind(this)
this.getValue = this.getValue.bind(this)
this.state = {
value: this.props.selectedValue || this.props.defaultValue || []
}
}
getChildContext() {
const checkboxGroup = {
name: this.props.name,
checkedValues: this.state.value,
onChange: this._onCheckboxChange
}
return { checkboxGroup }
}
componentWillReceiveProps(newProps) {
if (newProps.selectedValue) {
this.setState({
value: newProps.selectedValue
})
}
}
render() {
const { Component, name, selectedValue, onChange, children, ...rest } = this.props
return <Component {...rest}>{children}</Component>
}
getValue() {
return this.state.value
}
_isControlledComponent() {
return Boolean(this.props.selectedValue)
}
_onCheckboxChange(checkboxValue, event) {
let newValue
if (event.target.checked) {
newValue = this.state.value.concat(checkboxValue)
} else {
newValue = this.state.value.filter(v => v !== checkboxValue)
}
if (this._isControlledComponent()) {
this.setState({ value: this.props.selectedValue })
} else {
this.setState({ value: newValue })
}
if (typeof this.props.onChange === 'function') {
this.props.onChange(newValue, event, this.props.name)
}
}
}