How do I use radio buttons in React?
Asked Answered
D

4

13

I'm making a form, and I was in need of a radio input. How do I get the checked radio input in a onSubmit-function, what is the correct way?

This is my code, I myRadioInput-variable to contain either Option A or Option B when I submit:

React.createClass({
    handleSubmit: function() {
        e.preventDefault();
        var myTextInput = this.refs.myTextInput.getDOMNode().value.trim();
        var myRadioInput = "How ?";
    },
    render: function() {
        return (
            <form onSubmit={this.handleSubmit}>
                <input type="text" ref="myTextInput" />
                <label>
                    <span>Option A</span>
                    <input type="radio" name="myRadioInput" value="Option A"/>
                </label>
                <label>
                    <span>Option B</span>
                    <input type="radio" name="myRadioInput" value="Option B"/>
                </label>
                <input type="submit" value="Submit this"/>
            </form>
        )
    }
});
Dalenedalenna answered 17/4, 2015 at 8:29 Comment(1)
possible duplicate of How to use radio buttons in ReactJS?Myra
M
8

You shouldn't use refs to get access to DOM nodes and inspect their value. Instead you should link the inputs value to a property on the component state.

Here are some examples of how to do it: https://facebook.github.io/react/docs/two-way-binding-helpers.html

Magnetograph answered 17/4, 2015 at 8:32 Comment(7)
Thanks, but I don't agree that one should necessarily update state when developing simple forms that don't need real-time validation. Having everything in one submit-handler makes the component much simpler, and I don't need to worry about mixins or state.Dalenedalenna
And I don't agree with that, but that's okey.Magnetograph
@Dalenedalenna if you were using state, this would be trivial. And the motivation for using it even when it's not really needed is that it makes changing it in response to changing requirements easy.Tijerina
I seem to agree now :)Dalenedalenna
But isn't inspecting event.target.value the same as using refs.input.value?Honkytonk
Right, it is the same. Also, if you have a radio and want to apply .active only whence target.checked === true, you're in a tough spot because this class gets applied onchange -- which doesn't fire on-change but rather on-selected. So when another radio in the group is selected, both radios now have .active. It totally makes me hate my life.Ramify
@AndersEkdahl why shouldn't you use refs to access DOM nodes? Doesn't it become more expensive to have to update the state for every input field change, as well as taking up more code?Splanchnic
M
12

If you make sure all your form elements have name attributes, you can extract data from the form onSubmit using form.elements:

handleSubmit: function(e) {
  e.preventDefault()
  var form = e.target
  var myTextInput = form.elements.myTextInput.value
  var myRadioInput = form.elements.myRadioInput.value
  // ...
}

In modern browsers, form.elements.myRadioInput should be a RadioNodeList which has a .value corresponding to the selected value, but when that's not supported you will get a NodeList or HTMLCollection of nodes which must be iterated over to find the selected value.


I also have a reusable React component - <AutoForm> - which uses a generic implementation of data extraction from form.elements for you. I've used it in the snippet below:

<meta charset="UTF-8">
<script src="http://fb.me/react-0.13.1.js"></script>
<script src="http://fb.me/JSXTransformer-0.13.1.js"></script>
<script src="https://cdn.rawgit.com/insin/react-auto-form/master/dist/react-auto-form.js"></script>
<div id="app"></div>
<script type="text/jsx;harmony=true">void function() { "use strict";
 
var Example = React.createClass({
    getInitialState() {
        return {submittedData: null}
    },

    handleSubmit(e, submittedData) {
        e.preventDefault()
        this.setState({submittedData})
    },

    render() {
        return <div>
            <AutoForm onSubmit={this.handleSubmit}>
                <input type="text" name="myTextInput" />
                <label>
                    <span>Option A</span>
                    <input type="radio" name="myRadioInput" value="Option A"/>
                </label>
                <label>
                    <span>Option B</span>
                    <input type="radio" name="myRadioInput" value="Option B"/>
                </label>
                <input type="submit" value="Submit this"/>
            </AutoForm>
            {this.state.submittedData && <pre>
              {JSON.stringify(this.state.submittedData, null, 2)}
            </pre>}
        </div>
    }
});
 
React.render(<Example/>, document.getElementById('app'))
 
}()</script>
Most answered 17/4, 2015 at 9:28 Comment(2)
The e.target.elelments.myRaidoButton.value property on the onSubmit event was exactly what I needed. +1 for not having to setup a bunch of event handlers and manually track the state of which radio button is selected.Elrod
Agreed with @Jeremy. This answer is the one I needed. I'm happy to know the valueLink solution is there, it is interesting, but this just seems more standard to me.Spinode
M
8

You shouldn't use refs to get access to DOM nodes and inspect their value. Instead you should link the inputs value to a property on the component state.

Here are some examples of how to do it: https://facebook.github.io/react/docs/two-way-binding-helpers.html

Magnetograph answered 17/4, 2015 at 8:32 Comment(7)
Thanks, but I don't agree that one should necessarily update state when developing simple forms that don't need real-time validation. Having everything in one submit-handler makes the component much simpler, and I don't need to worry about mixins or state.Dalenedalenna
And I don't agree with that, but that's okey.Magnetograph
@Dalenedalenna if you were using state, this would be trivial. And the motivation for using it even when it's not really needed is that it makes changing it in response to changing requirements easy.Tijerina
I seem to agree now :)Dalenedalenna
But isn't inspecting event.target.value the same as using refs.input.value?Honkytonk
Right, it is the same. Also, if you have a radio and want to apply .active only whence target.checked === true, you're in a tough spot because this class gets applied onchange -- which doesn't fire on-change but rather on-selected. So when another radio in the group is selected, both radios now have .active. It totally makes me hate my life.Ramify
@AndersEkdahl why shouldn't you use refs to access DOM nodes? Doesn't it become more expensive to have to update the state for every input field change, as well as taking up more code?Splanchnic
A
0
    { items.map(item => 
    <span id="qn" key={item.qno}>{item.qno}</span>
    )}

    { items.map(item => 
    <span id="qd" key={item.qno}>{item.question}<br/>
    <br/>
  <input onClick={this.captureClick} type="radio" value="1" checked={this.state.option === "1"}
        onChange={this.handleChange}/>
    { item.options.map(option => 
    <span id="op" key={option.option1}>
    {option.option1}</span>
    )}<br/>
   <br/> <input onClick={this.captureClick} type="radio" value="2" checked={this.state.option === "2"}
        onChange={this.handleChange} />
    { item.options.map(option => 
    <span id="op" key={option.option2}>
    {option.option2}</span>
    )}<br/><br/>
    <input onClick={this.captureClick} type="radio" value="3" checked={this.state.option === "3"}
        onChange={this.handleChange} />
    { item.options.map(option => 
    <span id="op" key={option.option3}>
    {option.option3}</span>
    )}<br/><br/>

    <input onClick={this.captureClick} type="radio" value="4" checked={this.state.option === "4"}
        onChange={this.handleChange} />

    { item.options.map(option => 
    <span id="op" key={option.option4}>{option.option4}</span>
    )}<br/><br/>
  <button type="submit" className="save" onClick={this.onSave}>SAVE</button>  
  
    </span>

You can use Radio button's like this also

Apomict answered 6/8, 2018 at 10:31 Comment(2)
Some context / explanation would be helpful as only code answers tend to be difficult to understand.Tortuga
Defenitely .... I'm still working on this example and trying to store some values to the database when we click on these radio buttons...!Apomict
H
-2

i use this solution for radio button two way binding with active :

inside render() method:

const items = [
    {label: 'one', checked: false},
    {label: 'two', checked: true},
    {label: 'three', checked: true}
];

items.map((item, index) => (
    <div className={`radioItem (item.checked) ? 'active' : ''`}>
        <label>
            {item.label}
            <input type="radio"
                   name="address"
                   value={item.label}
                   onClick={(e)=>{
                       $('.radioItem').filter('.active').removeClass('active');
                       $(e.currentTarget).closest('.radioItem').addClass('active');
                   }}
                   ref={elm => $(elm).prop('checked', item.checked)}
            />
        </label>
    </div>
))
Hae answered 7/3, 2018 at 7:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.