Skip to content

Instantly share code, notes, and snippets.

@jonjaques
Created June 23, 2015 23:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonjaques/5a1673e2afd0b8736ebe to your computer and use it in GitHub Desktop.
Save jonjaques/5a1673e2afd0b8736ebe to your computer and use it in GitHub Desktop.
React Bootstrap ButtonGroup with Radio/Checkbox behavior
import React from 'react'
import { ButtonGroup } from 'react-bootstrap'
export default React.createClass({
propTypes: {
children: React.PropTypes.node,
type: React.PropTypes.oneOf(['checkbox', 'radio']),
value: React.PropTypes.any,
onChange: React.PropTypes.func,
valueLink: React.PropTypes.shape({
value: React.PropTypes.any,
requestChange: React.PropTypes.func.isRequired
})
},
getDefaultProps() {
return {
value: {},
valueLink: null,
onChange: ()=> {},
}
},
getValueLink: function(props) {
let { onChange, value } = props
return props.valueLink || {
value: value,
requestChange: onChange
}
},
handleClick(child) {
let { value, requestChange } = this.getValueLink(this.props)
let keys = this.getChildKeys()
let key = child.props.eventKey
if (this.props.type === 'radio') {
keys.forEach(k => value[k] = (k === key) ? true : false)
} else {
keys.forEach(k => value[k] = (k === key) ? !value[k] : value[k])
}
requestChange(value)
},
getChildKeys() {
let keys = []
React.Children.forEach(this.props.children, (child) => {
keys.push(child.props.eventKey)
})
return keys
},
renderChildren() {
return React.Children.map(this.props.children, (child)=> {
let value = this.getValueLink(this.props).value || {}
let isActive = value[child.props.eventKey] || false
return React.cloneElement(child, {
active: isActive,
onClick: this.handleClick.bind(this, child)
})
})
},
render() {
return <ButtonGroup className={this.props.className}
bsSize={this.props.bsSize}>
{this.renderChildren()}
</ButtonGroup>
}
})
/*
works like a standard controlled input...
DOES NOT work without it, so you must either supply
a value + onChange or a valueLink
*/
import ButtonGroupSelect from './buttonselect'
export default React.createClass({
mixins: [
React.addons.LinkedStateMixin
],
handleRadioSelect(values) {
console.log(values) // { foo: true, bar: false, baz: false }
this.setState({ radio1: values })
},
render() {
return <div>
<ButtonGroupSelect type="radio" value={this.state.radio1} onChange={this.handleRadioSelect}>
<Button eventKey="foo">Foo</Button>
<Button eventKey="bar">Bar</Button>
<Button eventKey="baz">Baz</Button>
</ButtonGroupSelect>
<ButtonGroupSelect type="checkbox" valueLink={this.linkState('radio2')}>
<Button eventKey="test1">Test 1</Button>
<Button eventKey="test2">Test 2</Button>
</ButtonGroupSelect>
</div>
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment