I want to have a list of radio buttons, with one option being a freestyle 'Other' text box that lets the user enter their own text.
Here I have a working sandbox of everything I want to do:
https://codesandbox.io/s/r4oo5q8q5o
handleChange = event => {
this.setState({
value: event.target.value
});
};
selectItem = item => {
this.setState({
selectedItem: item
});
};
handleOtherChange = event => {
this.setState({
otherText: event.target.value
});
this.selectItem(
//Todo put in right format
this.state.otherText
);
};
focusOther = () => {
this.setState({
value: "Other"
});
this.selectItem(this.state.otherText);
};
render() {
const { classes, items } = this.props;
const { value } = this.state;
return (
<div className={classes.root}>
<Typography>
{" "}
Selected item is: {JSON.stringify(this.state.selectedItem)}
</Typography>
<FormControl component="fieldset" fullWidth>
<RadioGroup value={this.state.value} onChange={this.handleChange}>
{items.map(v => (
<FormControlLabel
value={v.name}
control={<Radio />}
label={v.name}
key={v.name}
onChange={() => this.selectItem(v)}
/>
))}
<FormControlLabel
value="Other"
control={<Radio />}
label={
<TextField
placeholder="other"
onChange={this.handleOtherChange}
onFocus={this.focusOther}
/>
}
onChange={() => this.selectItem(this.state.otherText)}
/>
</RadioGroup>
</FormControl>
</div>
);
}
}
Now what I want to do is make the 'Other' text box its own component.
Here's my attempt:
https://codesandbox.io/s/ryomnpw1o
export default class OtherRadioButton extends React.Component {
constructor() {
super();
this.state = {
text: null
};
}
handleTextChange = event => {
this.setState({
text: event.target.value
});
this.props.onChange(this.state.text);
};
focusOther = () => {
this.props.onFocus(this.props.value);
this.props.onChange(this.state.text);
};
render() {
return (
<FormControlLabel
value={this.props.value}
control={<Radio />}
label={
<TextField
placeholder="other"
onChange={this.handleTextChange}
onFocus={this.focusOther}
/>
}
onChange={this.focusOther}
/>
);
}
}
Used with:
<OtherRadioButton
value="Other"
onFocus={v => this.setState({ value: v})}
onChange={v => this.selectItem(v)}
/>
As you can see - the value of the free text is propagating back fine - but the RadioGroup seems like it's not aware of the FormGroupLabel's value.
Why is this, and how would I solve this?
Use the onChange prop of your <RadioGroup> to hook in to when the selection changes, store it in your state and use this in the value prop of your containing <RadioGroup> . You should add an event listener and then update your state based on the value you can get from the event.
The easiest way to achieve this is by wrapping the Radio without any padding, in a Container and then setting your custom Margin and Padding as(if) required. This did the trick.
Using a Radio Button Group with a FormSet up a form with a radio button group like this. As you can see in the above example, in the form there are three different radio buttons along with the submit button, and each radio button is attached with one onChange function, called onValueChange() .
To create each radio button option, create a RadioButton in your layout. However, because radio buttons are mutually exclusive, you must group them together inside a RadioGroup . By grouping them together, the system ensures that only one radio button can be selected at a time.
You can check the RadioGroup source code here. And I have written my own code to better illustrate how it can be fixed. See here: https://codesandbox.io/s/mz1wn4n33j
RadioGroup creates some props to its FormControlLabel/RadioButton children. By creating your own customized radio button in a different component, these props are not passed to FormControlLabel/RadioButton.
You can fix these by passing the props to your FormControlLabel in your custom RadioButton.
<FormControlLabel
value={this.props.value} //Pass this
onChange={this.props.onChange} //Pass this one too
checked={this.props.checked} //Also this
control={<Radio name="gender" />}
label={
<TextField
id="standard-bare"
defaultValue={this.props.defaultValue}
margin="normal"
onChange={this.props.onTextChange}
/>
}
/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With