Skip to content

Instantly share code, notes, and snippets.

@Munter
Last active December 7, 2020 09:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Munter/7c6892d950816e049bf2 to your computer and use it in GitHub Desktop.
Save Munter/7c6892d950816e049bf2 to your computer and use it in GitHub Desktop.
React radio input group component, giving you a single selected value across a range of radio inputs in its children
define(function (require) {
var expect = require('unexpected');
var React = require('react');
var ReactTestUtils = React.addons.TestUtils;
var RadioGroup = require('jsx!../RadioGroupComponent.jsx');
describe('RadioGroupComponent', function() {
it('should render', function() {
var instance = ReactTestUtils.renderIntoDocument(<RadioGroup />);
expect(instance, 'to be defined');
});
describe('value', function () {
it('should not check any radio buttons when there is no value', function () {
var instance = ReactTestUtils.renderIntoDocument(
<RadioGroup>
<input type="radio" value="one" />
<input type="radio" value="two" />
</RadioGroup>);
var inputs = Array.prototype.slice.call(instance.getDOMNode().querySelectorAll('input[type="radio"]'));
expect(inputs, 'to have length', 2);
expect(inputs, 'to be an array whose items satisfy', function (input) {
expect(input.checked, 'to be', false);
});
});
it('should not check any radio buttons when there is a value, but no input has the value', function () {
var instance = ReactTestUtils.renderIntoDocument(
<RadioGroup value="foo">
<input type="radio" value="one" />
<input type="radio" value="two" />
</RadioGroup>);
var inputs = Array.prototype.slice.call(instance.getDOMNode().querySelectorAll('input[type="radio"]'));
expect(inputs, 'to have length', 2);
expect(inputs, 'to be an array whose items satisfy', function (input) {
expect(input.checked, 'to be', false);
});
});
it('should check the radio button with the corresponding value when a value is defined', function () {
var instance = ReactTestUtils.renderIntoDocument(
<RadioGroup value="two">
<input type="radio" value="one" />
<input type="radio" value="two" />
</RadioGroup>);
var inputs = Array.prototype.slice.call(instance.getDOMNode().querySelectorAll('input[type="radio"]'));
expect(inputs, 'to have length', 2);
expect(inputs[0], 'to satisfy', function (input) {
expect(input.checked, 'to be', false);
});
// console.log(inputs[1].outerHTML);
// expect(inputs[1], 'to satisfy', function (input) {
// expect(input.checked, 'to be', true);
// });
});
});
});
});
define(function(require) {
'use strict';
var React = require('react');
var traverseChildren = (children, cb) => {
React.Children.forEach(children, (child) => {
cb(child);
if (child.props && child.props.children) {
traverseChildren(child.props.children, cb);
}
});
};
var RadioGroupComponent = React.createClass({
displayName: 'RadioGroupComponent',
propTypes: {
name: React.PropTypes.string,
value: React.PropTypes.string,
onChange: React.PropTypes.func
},
componentWillMount() {
this._initChildren(this.props);
},
componentWillUpdate(nextProps, nextState) {
this._initChildren(nextProps);
},
_initChildren(nextProps) {
var hasChangeHandler = typeof nextProps.onChange === 'function';
traverseChildren(nextProps.children, (child) => {
if (child.type === 'input' && child.props.type === 'radio') {
if (hasChangeHandler) {
child.props.onChange = this._handleChange;
}
if (nextProps.name && !child.props.name) {
child.props.name = nextProps.name;
}
if (nextProps.value && nextProps.value === child.props.value) {
if (hasChangeHandler) {
child.props.checked = true;
} else {
child.props.defaultChecked = true;
}
}
}
});
},
_handleChange(e) {
if (e.target.checked) {
this.props.onChange(e.target.value);
}
},
render() {
return <div>{this.props.children}</div>;
}
});
return RadioGroupComponent;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment