diff --git a/packages/material-ui/src/RadioGroup/RadioGroup.js b/packages/material-ui/src/RadioGroup/RadioGroup.js
index 02f139ac9a2aac..47a53c94f5c615 100644
--- a/packages/material-ui/src/RadioGroup/RadioGroup.js
+++ b/packages/material-ui/src/RadioGroup/RadioGroup.js
@@ -9,6 +9,15 @@ import { createChainedFunction, find } from '../utils/helpers';
class RadioGroup extends React.Component {
radios = [];
+ state = {
+ value: null,
+ };
+
+ constructor(props) {
+ super();
+ this.isControlled = props.value != null;
+ }
+
focus = () => {
if (!this.radios || !this.radios.length) {
return;
@@ -30,15 +39,22 @@ class RadioGroup extends React.Component {
focusRadios[0].focus();
};
- handleRadioChange = (event, checked) => {
- if (checked && this.props.onChange) {
+ handleChange = event => {
+ if (!this.isControlled) {
+ this.setState({
+ value: event.target.value,
+ });
+ }
+
+ if (this.props.onChange) {
this.props.onChange(event, event.target.value);
}
};
render() {
- const { children, name, value, onChange, ...other } = this.props;
+ const { children, name, value: valueProp, onChange, ...other } = this.props;
+ const value = this.isControlled ? valueProp : this.state.value;
this.radios = [];
return (
@@ -64,7 +80,7 @@ class RadioGroup extends React.Component {
}
},
checked: value === child.props.value,
- onChange: createChainedFunction(child.props.onChange, this.handleRadioChange),
+ onChange: createChainedFunction(child.props.onChange, this.handleChange),
});
})}
diff --git a/packages/material-ui/src/RadioGroup/RadioGroup.test.js b/packages/material-ui/src/RadioGroup/RadioGroup.test.js
index 450862fddef2e8..4924aeb4f3fe39 100644
--- a/packages/material-ui/src/RadioGroup/RadioGroup.test.js
+++ b/packages/material-ui/src/RadioGroup/RadioGroup.test.js
@@ -37,6 +37,25 @@ describe('', () => {
assert.strictEqual(handleKeyDown.args[0][0], event);
});
+ it('should support uncontrolled mode', () => {
+ const wrapper = shallow(
+
+
+ ,
+ );
+
+ const radio = wrapper.children().first();
+ const event = { target: { value: 'one' } };
+ radio.simulate('change', event, true);
+ assert.strictEqual(
+ wrapper
+ .children()
+ .first()
+ .props().checked,
+ true,
+ );
+ });
+
describe('imperative focus()', () => {
let wrapper;
@@ -134,20 +153,6 @@ describe('', () => {
assert.strictEqual(handleChange.calledWith(event), true);
});
- it('should not fire onChange if not checked', () => {
- const handleChange = spy();
- const wrapper = shallow(
-
-
-
- ,
- );
-
- const internalRadio = wrapper.children().first();
- internalRadio.simulate('change', { target: { value: 'woofRadioGroup' } }, false);
- assert.strictEqual(handleChange.callCount, 0);
- });
-
it('should chain the onChange property', () => {
const handleChange1 = spy();
const handleChange2 = spy();