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>
        )
    }
});
andersem
  • 724
  • 1
  • 8
  • 19
  • 3
    possible duplicate of [How to use radio buttons in ReactJS?](http://stackoverflow.com/questions/27784212/how-to-use-radio-buttons-in-reactjs) – hopper Jul 28 '15 at 20:20

4 Answers4

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>
Jonny Buchanan
  • 61,926
  • 17
  • 143
  • 150
  • 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. – Jeremy Aug 06 '15 at 17:48
  • 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. – nackjicholson Aug 27 '16 at 03:54
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

Anders Ekdahl
  • 22,685
  • 4
  • 70
  • 59
  • 4
    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. – andersem Apr 17 '15 at 08:45
  • And I don't agree with that, but that's okey. – Anders Ekdahl Apr 17 '15 at 08:51
  • @andersem 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. – Brigand Apr 17 '15 at 09:14
  • I seem to agree now :) – andersem Apr 24 '15 at 08:21
  • 4
    But isn't inspecting `event.target.value` the same as using `refs.input.value`? – Petr Peller Apr 02 '16 at 19:16
  • 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. – Cody May 22 '16 at 06:22
  • @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? – Ozymandias Jul 15 '16 at 11:42
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

Ashish Kamble
  • 2,555
  • 3
  • 21
  • 29
  • 1
    Some context / explanation would be helpful as only code answers tend to be difficult to understand. – UditS Aug 06 '18 at 10:39
  • Defenitely .... I'm still working on this example and trying to store some values to the database when we click on these radio buttons...! – Jayakar Pj Aug 06 '18 at 10:46
-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>
))