UNPKG

react-simple-radio-group

Version:

A React mixin for linking form fields to a deep structure of data within the component's state.

232 lines (182 loc) 6.02 kB
'use strict'; var React = require('react'); var assign = require('object-assign'); var ReactDOM = require('react-dom'); function emptyFn() { } module.exports = React.createClass({ displayName: 'ReactRadioGroup', propTypes: { name: React.PropTypes.string.isRequired, items: function (props, name) { if (!props.children && !props.items) { return new Error('Your component has no children. In this case, you should specify an items array.') } } }, componentDidUpdate: function () { if (!this.shouldGenerateChildren()) { this.setRadioNames() this.setCheckedRadio() } }, componentDidMount: function () { if (!this.shouldGenerateChildren()) { this.setRadioNames() this.setCheckedRadio() } }, setCheckedRadio: function () { var value = this.props.value != null ? this.props.value : this.state.defaultValue this.someRadio(function (radio) { if (radio.value == value) { radio.checked = true return true } }) }, setRadioNames: function () { this.forEachRadio(function (radio) { if ( ! radio.getAttribute("name") ) radio.setAttribute('name', this.props.name); }) }, someRadio: function (fn) { var $radios = this.getRadios() return [].some.call($radios, fn, this) }, forEachRadio: function (fn) { var $radios = this.getRadios() return [].forEach.call($radios, fn, this) }, getRadios: function () { return ReactDOM.findDOMNode(this).querySelectorAll('input[type="radio"]') }, getDefaultProps: function () { return { defaultLabelStyle: { cursor: 'pointer' }, defaultInputStyle: { cursor: 'pointer' } } }, getInitialState: function () { return { defaultValue: this.props.defaultValue } }, render: function () { var props = this.prepareProps(this.props, this.state) return React.createElement("div", React.__spread({}, props)) }, getValue: function () { if (this.value == undefined) { this.value = this.state.defaultValue } return this.value }, handleChange: function (event) { var isRadio = event.target.type == 'radio'; var fn = this.props.onChange || emptyFn; var value = this.value = event.target.value; if(!isRadio){ return; } if(event.target.getAttribute('name') != this.props.name){ return; } fn(value, event) if (this.props.value == null) { this.setState({ defaultValue: value }) } }, shouldGenerateChildren: function () { return !this.props.children }, prepareProps: function (thisProps, state) { var props = {} assign(props, thisProps) if (this.shouldGenerateChildren()) { props.labelStyle = this.prepareLabelStyle(props, state) props.inputStyle = this.prepareInputStyle(props, state) props.children = this.prepareChildren(props, state) } props.onChange = this.handleChange return props }, prepareLabelStyle: function (props) { return assign({}, props.defaultLabelStyle, props.labelStyle) }, prepareInputStyle: function (props) { return assign({}, props.defaultInputStyle, props.inputStyle) }, prepareChildren: function (props, state) { var checkedValue = props.value != null ? props.value : state.defaultValue return (props.items || []).map(function (item, index, arr) { var inputStyle = assign({}, props.inputStyle) var labelStyle = assign({}, props.labelStyle) var checked var value var children if (typeof item === 'string') { value = item checked = checkedValue == value children = item } else { value = item.value children = item.label || item.value || item.children checked = checkedValue == value if (item.inputStyle) { assign(inputStyle, item.inputStyle) } if (item.style) { assign(labelStyle, item.style) } } if (checked) { assign(inputStyle, props.checkedInputStyle) assign(labelStyle, props.checkedLabelStyle) if (checked && item && item.checkedStyle) { assign(labelStyle, item.checkedStyle) } } var inputProps = { checked: checked, value: value, name: props.name, type: 'radio', style: inputStyle, onChange: emptyFn } var radioProps = { key: index, checked: checked, index: index, name: props.name, value: value, style: labelStyle, inputProps: inputProps, children: [ React.createElement("input", React.__spread({}, inputProps)), children ] } var renderFn = props.renderRadio var result if (renderFn) { result = renderFn(radioProps, index, arr) } if (result === undefined) { result = React.createElement("label", React.__spread({}, radioProps)) } return result }, this) } })