OnChange event handler for radio button (INPUT type="radio") doesn't work as one value

JavascriptHtmlCross Browser

Javascript Problem Overview


I'm looking for a generalized solution for this.

Consider 2 radio type inputs with the same name. When submitted, the one that is checked determines the value that gets sent with the form:

<input type="radio" name="myRadios" onchange="handleChange1();" value="1" />
<input type="radio" name="myRadios" onchange="handleChange2();" value="2" />

The change event does not fire when a radio button is de-selected. So if the radio with value="1" is already selected and the user selects the second, handleChange1() does not run. This presents a problem (for me anyway) in that there is no event where I can catch this de-selection.

What I would like is a workaround for the onChange event for the checkbox group value or alternatively, an onCheck event that detects not only when a radio button is checked but also when it is unchecked.

I'm sure some of you have run into this problem before. What are some workarounds (or ideally what is the right way to handle this)? I just want to catch the change event, access the previously checked radio as well as the newly checked radio.

P.S.
onClick seems like a better (cross-browser) event to indicate when a radio button is checked but it still does not solve the unchecked problem.

I suppose it makes sense why onChange for a checkbox type does work in a case like this since it changes the value that it submits when you check or un-check it. I wish the radio buttons behaved more like a SELECT element's onChange but what can you do...

Javascript Solutions


Solution 1 - Javascript

var rad = document.myForm.myRadios;
var prev = null;
for (var i = 0; i < rad.length; i++) {
    rad[i].addEventListener('change', function() {
        (prev) ? console.log(prev.value): null;
        if (this !== prev) {
            prev = this;
        }
        console.log(this.value)
    });
}

<form name="myForm">
  <input type="radio" name="myRadios"  value="1" />
  <input type="radio" name="myRadios"  value="2" />
</form>

Here's a JSFiddle demo: https://jsfiddle.net/crp6em1z/

Solution 2 - Javascript

I would make two changes:

<input type="radio" name="myRadios" onclick="handleClick(this);" value="1" />
<input type="radio" name="myRadios" onclick="handleClick(this);" value="2" />
  1. Use the onclick handler instead of onchange - you're changing the "checked state" of the radio input, not the value, so there's not a change event happening.
  2. Use a single function, and pass this as a parameter, that will make it easy to check which value is currently selected.

ETA: Along with your handleClick() function, you can track the original / old value of the radio in a page-scoped variable. That is:

var currentValue = 0;
function handleClick(myRadio) {
    alert('Old value: ' + currentValue);
    alert('New value: ' + myRadio.value);
    currentValue = myRadio.value;
}

var currentValue = 0;
function handleClick(myRadio) {
    alert('Old value: ' + currentValue);
    alert('New value: ' + myRadio.value);
    currentValue = myRadio.value;
}

<input type="radio" name="myRadios" onclick="handleClick(this);" value="1" />
<input type="radio" name="myRadios" onclick="handleClick(this);" value="2" />

Solution 3 - Javascript

As you can see from this example: http://jsfiddle.net/UTwGS/

HTML:

<label><input type="radio" value="1" name="my-radio">Radio One</label>
<label><input type="radio" value="2" name="my-radio">Radio One</label>

jQuery:

$('input[type="radio"]').on('click change', function(e) {
    console.log(e.type);
});

both the click and change events are fired when selecting a radio button option (at least in some browsers).

I should also point out that in my example the click event is still fired when you use tab and the keyboard to select an option.

So, my point is that even though the change event is fired is some browsers, the click event should supply the coverage you need.

Solution 4 - Javascript

You can add the following JS script

<script>
    function myfunction(event) {
        alert('Checked radio with ID = ' + event.target.id);
    }
    document.querySelectorAll("input[name='myRadios']").forEach((input) => {
        input.addEventListener('change', myfunction);
    });
</script>

Solution 5 - Javascript

What about using the change event of Jquery?

$(function() {
    $('input:radio[name="myRadios"]').change(function() {
        if ($(this).val() == '1') {
            alert("You selected the first option and deselected the second one");
        } else {
            alert("You selected the second option and deselected the first one");
        }
    });
});

jsfiddle: http://jsfiddle.net/f8233x20/

Solution 6 - Javascript

Store the previous checked radio in a variable:
http://jsfiddle.net/dsbonev/C5S4B/

HTML
<input type="radio" name="myRadios" value="1" /> 1
<input type="radio" name="myRadios" value="2" /> 2
<input type="radio" name="myRadios" value="3" /> 3
<input type="radio" name="myRadios" value="4" /> 4
<input type="radio" name="myRadios" value="5" /> 5
JS
var changeHandler = (function initChangeHandler() {
    var previousCheckedRadio = null;
    
    var result = function (event) {
        var currentCheckedRadio = event.target;
        var name = currentCheckedRadio.name;
        
        if (name !== 'myRadios') return;
        
        //using radio elements previousCheckedRadio and currentCheckedRadio
    
        //storing radio element for using in future 'change' event handler
        previousCheckedRadio = currentCheckedRadio;
    };

    return result;
})();

document.addEventListener('change', changeHandler, false);
JS EXAMPLE CODE
var changeHandler = (function initChangeHandler() {
    var previousCheckedRadio = null;

    function logInfo(info) {
        if (!console || !console.log) return;
            
        console.log(info);
    }

    function logPrevious(element) {
        if (!element) return;
        
        var message = element.value + ' was unchecked';
    
        logInfo(message);
    }

    function logCurrent(element) {
        if (!element) return;
        
        var message = element.value + ' is checked';
    
        logInfo(message);
    }
    
    var result = function (event) {
        var currentCheckedRadio = event.target;
        var name = currentCheckedRadio.name;
        
        if (name !== 'myRadios') return;
        
        logPrevious(previousCheckedRadio);
        logCurrent(currentCheckedRadio);
    
        previousCheckedRadio = currentCheckedRadio;
    };

    return result;
})();

document.addEventListener('change', changeHandler, false);

Solution 7 - Javascript

I don't think there is any way other then storing the previous state. Here is the solution with jQuery

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> 
<script type="text/javascript">
    var lastSelected;
    $(function () {
        //if you have any radio selected by default
        lastSelected = $('[name="myRadios"]:checked').val();
    });
    $(document).on('click', '[name="myRadios"]', function () {
        if (lastSelected != $(this).val() && typeof lastSelected != "undefined") {
            alert("radio box with value " + $('[name="myRadios"][value="' + lastSelected + '"]').val() + " was deselected");
        }
        lastSelected = $(this).val();
    });
</script>

<input type="radio" name="myRadios" value="1" />
<input type="radio" name="myRadios" value="2" />
<input type="radio" name="myRadios" value="3" />
<input type="radio" name="myRadios" value="4" />
<input type="radio" name="myRadios" value="5" />
    

After thinking about it a bit more, I decided to get rid of the variable and add/remove class. Here is what I got: http://jsfiddle.net/BeQh3/2/

Solution 8 - Javascript

I realize this is an old issue, but this snippet of code works for me. Perhaps someone in the future will find it useful:

<h2>Testing radio functionality</h2>
<script type="text/javascript">var radioArray=[null];</script>
<input name="juju" value="button1" type="radio" onclick="radioChange('juju','button1',radioArray);" />Button 1
<input name="juju" value="button2" type="radio" onclick="radioChange('juju','button2',radioArray);" />Button 2
<input name="juju" value="button3" type="radio" onclick="radioChange('juju','button3',radioArray);" />Button 3
<br />

<script type="text/javascript">
function radioChange(radioSet,radioButton,radioArray)
  {
  //if(radioArray instanceof Array) {alert('Array Passed');}
  var oldButton=radioArray[0];
  if(radioArray[0] == null)
    {
    alert('Old button was not defined');
    radioArray[0]=radioButton;
    }
  else
    {
    alert('Old button was set to ' + oldButton);
    radioArray[0]=radioButton;
    }
  alert('New button is set to ' + radioArray[0]);
  }
</script>

Solution 9 - Javascript

As you can see here: http://www.w3schools.com/jsref/event_onchange.asp The onchange attribute is not supported for radio buttons.

The first SO question linked by you gives you the answer: Use the onclick event instead and check the radio button state inside of the function it triggers.

Solution 10 - Javascript

Yes there is no change event for currently selected radio button. But problem is when each radio button is taken as a separate element. Instead a radio group should be considered a single element like select. So change event is triggered for that group. If it is a select element we never worry about each option in it, but take only the selected option. We store the current value in a variable which will become the previous value, when a new option is selected. Similarly you have to use a separate variable for storing value of checked radio button.

If you want to identify the previous radio button, you have to loop on mousedown event.

var radios = document.getElementsByName("myRadios");
var val;
for(var i = 0; i < radios.length; i++){
    if(radios[i].checked){
        val = radios[i].value;
    }
}

see this : http://jsfiddle.net/diode/tywx6/2/

Solution 11 - Javascript

Easiest and power full way

read only radio inputs using getAttribute

document.addEventListener('input',(e)=>{

if(e.target.getAttribute('name')=="myRadios")
console.log(e.target.value)
})

<input type="radio" name="myRadios" value="1" /> 1
<input type="radio" name="myRadios" value="2" /> 2

Solution 12 - Javascript

This is just off the top of my head, but you could do an onClick event for each radio button, give them all different IDs, and then make a for loop in the event to go through each radio button in the group and find which is was checked by looking at the 'checked' attribute. The id of the checked one would be stored as a variable, but you might want to use a temp variable first to make sure that the value of that variable changed, since the click event would fire whether or not a new radio button was checked.

Solution 13 - Javascript

<input type="radio" name="brd" onclick="javascript:brd();" value="IN">   
<input type="radio" name="brd" onclick="javascript:brd();" value="EX">` 
<script type="text/javascript">
  function brd() {alert($('[name="brd"]:checked').val());}
</script>

Solution 14 - Javascript

If you want to avoid inline script, you can simply listen for a click event on the radio. This can be achieved with plain Javascript by listening to a click event on

for (var radioCounter = 0 ; radioCounter < document.getElementsByName('myRadios').length; radioCounter++) {
      document.getElementsByName('myRadios')[radioCounter].onclick = function() {
        //VALUE OF THE CLICKED RADIO ELEMENT
        console.log('this : ',this.value);
      }
}

Solution 15 - Javascript

this works for me

<input ID="TIPO_INST-0" Name="TIPO_INST" Type="Radio" value="UNAM" onchange="convenio_unam();">UNAM

<script type="text/javascript">
			function convenio_unam(){
				if(this.document.getElementById('TIPO_INST-0').checked){
					$("#convenio_unam").hide();
				}else{
					$("#convenio_unam").show();	
				}								
			}
</script>

Solution 16 - Javascript

This is the easiest and most efficient function to use just add as many buttons as you want to the checked = false and make the onclick event of each radio buttoncall this function. Designate a unique number to each radio button

function AdjustRadios(which) 
{
    if(which==1)
         document.getElementById("rdpPrivate").checked=false;
    else if(which==2)
         document.getElementById("rdbPublic").checked=false;
}

Solution 17 - Javascript

For some reason, the best answer does not works for me.

I improved best answer by use

    var overlayType_radio = document.querySelectorAll('input[type=radio][name="radio_overlaytype"]');

Original best answer use:

      var rad = document.myForm.myRadios;

The others keep the same, finally it works for me.

var overlayType_radio = document.querySelectorAll('input[type=radio][name="radio_overlaytype"]');
                              console.log('overlayType_radio', overlayType_radio)

                              var prev = null;
                              for (var i = 0; i < overlayType_radio.length; i++) {
                                  overlayType_radio[i].addEventListener('change', function() {
                                      (prev) ? console.log('radio prev value',prev.value): null;
                                      if (this !== prev) {
                                          prev = this;
                                      }
                                      console.log('radio now value ', this.value)
                                  });
                              }

html is:

<div id='overlay-div'>
                        <fieldset>
                                <legend> Overlay Type </legend>
                                
                                <p>
                                    <label>
                                      <input class='with-gap' id='overlayType_image' value='overlayType_image' name='radio_overlaytype' type='radio' checked/>
                                      <span>Image</span> 
                                    </label>
                                </p>

                                <p>
                                  <label>
                                    <input class='with-gap' id='overlayType_tiled_image' value='overlayType_tiled_image' name='radio_overlaytype' type='radio' disabled/>
                                    <span> Tiled Image</span>   
                                </p>

                                <p>
                                  <label>
                                    <input class='with-gap' id='overlayType_coordinated_tile' value='overlayType_coordinated_tile' name='radio_overlaytype' type='radio'  disabled/>
                                    <span> Coordinated Tile</span>  
                                </p>

                                <p>
                                  <label>
                                    <input class='with-gap' id='overlayType_none' value='overlayType_none' name='radio_overlaytype' type='radio'/>
                                    <span> None </span>            
                                  </p>

                                  
                          </fieldset>
                       </div>

 var overlayType_radio = document.querySelectorAll('input[type=radio][name="radio_overlaytype"]');
                                  console.log('overlayType_radio', overlayType_radio)

                                  var prev = null;
                                  for (var i = 0; i < overlayType_radio.length; i++) {
                                      overlayType_radio[i].addEventListener('change', function() {
                                          (prev) ? console.log('radio prev value',prev.value): null;
                                          if (this !== prev) {
                                              prev = this;
                                          }
                                          console.log('radio now value ', this.value)
                                      });
                                  }

<div id='overlay-div'>
                            <fieldset>
                                    <legend> Overlay Type </legend>
                                    
                                    <p>
                                        <label>
                                          <input class='with-gap' id='overlayType_image' value='overlayType_image' name='radio_overlaytype' type='radio' checked/>
                                          <span>Image</span> 
                                        </label>
                                    </p>

                                    <p>
                                      <label>
                                        <input class='with-gap' id='overlayType_tiled_image' value='overlayType_tiled_image' name='radio_overlaytype' type='radio' />
                                        <span> Tiled Image</span>   
                                    </p>

                                    <p>
                                      <label>
                                        <input class='with-gap' id='overlayType_coordinated_tile' value='overlayType_coordinated_tile' name='radio_overlaytype' type='radio'  />
                                        <span> Coordinated Tile</span>  
                                    </p>

                                    <p>
                                      <label>
                                        <input class='with-gap' id='overlayType_none' value='overlayType_none' name='radio_overlaytype' type='radio'/>
                                        <span> None </span>            
                                      </p>

                                      
                              </fieldset>
                           </div>

jsfiddle click here

https://jsfiddle.net/hoogw/jetmkn02/1/

Solution 18 - Javascript

Tl;dr

'focusout' is dispatched before the 'change' event - example:

const radioName = 'radio';

// Add radios
document.body.innerHTML = `
<style>
input + label {
  margin-left: 1rem;
}
</style>
<form action="#" name="example-form">
  <fieldset>
    ${Array(5).fill(null, 0, 5).map((_, i) => {
        const offsetId = i + 1;
        const id = `radio-${offsetId}`;
        return `<label for="${id}">Radio ${offsetId}</label>
        <input type="radio" name="${radioName}" id="${id}" value="${offsetId}" />`;
      }).join('\n')}
  </fieldset>
</form>
`;

const {log} = console,

    form = document.forms['example-form']; 

form.addEventListener('submit', e => e.preventDefault());

form.addEventListener('change', e => {
    const {target} = e;
    if (target.matches(`[type="radio"][name="${radioName}"]`)) {
        log(`[${e.type}]: "${target.id}" selected;  Value: ${target.value}`);
    }
});

form.addEventListener('focusout', e => {
    const {target} = e,

        soonToBePrevValue = target && target.form ? 
            target.form.elements[radioName].value : null;
    
    if (!target.matches(`[type="radio"][name="${radioName}"]`) || !soonToBePrevValue) {
        return;
    }

    // value, for '[name="radio"]', contained in form, will change after 'focusout' event
    // has completed it's bubbling stage.
    log(`[${e.type}]: previously selected radio value: ` + 
        `${soonToBePrevValue}`);
        
    // log("Soon to be \"previous\" radio: ", target);
});

jsfiddle

Solution 19 - Javascript

<script>
    function radioClick(radio){
        alert()
    }
</script>

<label>Cash on delivery</label>
<input type="radio" onclick="radioClick('A')" name="payment_method" class="form-group">

<br>

<label>Debit/Credit card, GPay, Paytm etc..</label>
<input type="radio" onclick="radioClick('B')" name="payment_method" class="form-group">

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMatthewView Question on Stackoverflow
Solution 1 - JavascriptMichalView Answer on Stackoverflow
Solution 2 - JavascriptNate CookView Answer on Stackoverflow
Solution 3 - JavascriptPhilip WaltonView Answer on Stackoverflow
Solution 4 - JavascriptBuzzView Answer on Stackoverflow
Solution 5 - JavascriptRazan PaulView Answer on Stackoverflow
Solution 6 - JavascriptDimitar BonevView Answer on Stackoverflow
Solution 7 - JavascriptAlex OkrushkoView Answer on Stackoverflow
Solution 8 - JavascriptJohn KView Answer on Stackoverflow
Solution 9 - JavascriptConstantin GroßView Answer on Stackoverflow
Solution 10 - JavascriptDiodeView Answer on Stackoverflow
Solution 11 - JavascriptßãlãjîView Answer on Stackoverflow
Solution 12 - JavascriptAndrew LathamView Answer on Stackoverflow
Solution 13 - Javascriptumesh unnikrishnanView Answer on Stackoverflow
Solution 14 - JavascriptmareksView Answer on Stackoverflow
Solution 15 - JavascriptDoberonView Answer on Stackoverflow
Solution 16 - JavascriptJamaView Answer on Stackoverflow
Solution 17 - JavascripthoogwView Answer on Stackoverflow
Solution 18 - JavascriptelydelacruzView Answer on Stackoverflow
Solution 19 - Javascriptadhil muhammedView Answer on Stackoverflow