Le gestionnaire d'événements OnChange pour le bouton radio (INPUT type = «radio») ne fonctionne pas comme une valeur

191

Je recherche une solution généralisée pour cela.

Considérez 2 entrées de type radio avec le même nom. Une fois soumis, celui qui est coché détermine la valeur qui est envoyée avec le formulaire:

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

L'événement de modification ne se déclenche pas lorsqu'un bouton radio est désélectionné. Donc, si la radio avec valeur = "1" est déjà sélectionnée et que l'utilisateur sélectionne la seconde, handleChange1 () ne s'exécute pas. Cela pose un problème (pour moi en tout cas) dans la mesure où il n'y a pas d'événement où je puisse attraper cette désélection.

Ce que je voudrais, c'est une solution de contournement pour l'événement onchange pour la valeur du groupe de cases à cocher ou, alternativement, un événement oncheck qui détecte non seulement quand une radio est cochée, mais aussi quand elle est décochée.

Je suis sûr que certains d'entre vous ont déjà rencontré ce problème. Quelles sont les solutions de contournement (ou, idéalement, quelle est la bonne façon de gérer cela)? Je veux juste attraper l'événement de changement, accéder à la radio précédemment vérifiée ainsi qu'à la radio nouvellement vérifiée.

PS
onclick semble être un meilleur événement (cross-browser) pour indiquer quand une radio est vérifiée mais il ne résout toujours pas le problème non vérifié.

Je suppose qu'il est logique de savoir pourquoi onchange pour un type de case à cocher fonctionne dans un cas comme celui-ci, car il modifie la valeur qu'il soumet lorsque vous le cochez ou le décochez. Je souhaite que les boutons radio se comportent plus comme onchange d'un élément SELECT mais que pouvez-vous faire ...

Matthieu
la source

Réponses:

179

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>

Voici une démo de JSFiddle: https://jsfiddle.net/crp6em1z/

Michal
la source
4
Juste une note sur la raison pour laquelle j'ai choisi cela comme la bonne réponse: les gestionnaires d'événements de clic sont configurés sur chacun des boutons radio avec l'attribut name myRadiospour lire la variable prevqui contient la radio actuellement sélectionnée. Une comparaison est effectuée dans chaque gestionnaire de clics pour décider si la radio cliquée est la même que celle stockée dans prevet si ce n'est pas le cas, la radio actuellement cliquée y est stockée. Dans le gestionnaire de clics, vous avez accès à la prevradio précédemment sélectionnée: et à la radio actuellement sélectionnée:this
Matthew
26
Il serait préférable de mettre en cache la fonction en dehors de la boucle, afin que toutes les radios partagent le même gestionnaire d'événements (maintenant elles ont des gestionnaires identiques mais ce sont des fonctions différentes). Ou peut-être mettre toutes les radios dans un wrapper et utiliser la délégation d'événements
Oriol
1
@Oriol, ou quelqu'un de bien informé, pourriez-vous donner un exemple de (1) mise en cache en dehors de la boucle ou (2) wrapper + délégation d'événements?
Matt Voda
14
onclick ne fonctionne pas avec la sélection du clavier, vous pouvez l'utiliser rad[i].addEventListener('change', function(){ //your handler code })et cela fonctionnera à la fois pour la souris et le clavier
Juanmi Rodriguez
117

Je ferais deux changements:

<input type="radio" name="myRadios" onclick="handleClick(this);" value="1" />
<input type="radio" name="myRadios" onclick="handleClick(this);" value="2" />
  1. Utilisez le onclickgestionnaire au lieu de onchange- vous modifiez "l'état vérifié" de l'entrée radio, pas le value, donc il n'y a pas d'événement de changement.
  2. Utilisez une seule fonction et passez thisen paramètre, ce qui facilitera la vérification de la valeur actuellement sélectionnée.

ETA: avec votre handleClick()fonction, vous pouvez suivre la valeur d'origine / ancienne de la radio dans une variable de portée de page. C'est:

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" />

Nate Cook
la source
Merci, bien que cela ne résout pas le problème d'avoir à obtenir la radio précédemment vérifiée et que vous déclarez également quelque chose que d'autres utilisateurs ont déjà mentionné, à savoir utiliser "onclick" au lieu de "onchange". Je le savais depuis le début, mais je voulais attirer l'attention sur le fait que onchange ne fonctionne pas comme on pouvait s'y attendre et j'aimerais mieux le gérer.
Matthew
1
Vous utilisez JavaScript, non? Alors pourquoi ne pas simplement conserver une variable qui stocke le dernier bouton radio sélectionné connu? Si vous utilisez un seul gestionnaire, vous pouvez vérifier cette valeur stockée avant de la remplacer par la nouvelle valeur. +1
jmort253
13
@Matthew: Le onclickgestionnaire est juste mal nommé - il gère l'événement de sélection de bouton radio, que le bouton soit cliqué, touché ou activé en appuyant sur "Entrée" sur un clavier. Le onchangegestionnaire n'est pas approprié dans ce cas car la valeur de l'entrée ne change pas, seulement l'attribut coché / non coché. J'ai ajouté un exemple de script pour traiter la valeur précédente.
Nate Cook
1
"onClick" ne gérera pas l'événement si l'utilisateur a utilisé le clavier (tab + barre d'espace) pour sélectionner la radio (et c'est une pratique courante sur les grands formulaires).
HoldOffHunger
+1. "onChange ()" n'est pas un événement pouvant être déclenché dans ReactJS et c'est la seule solution. Source: github.com/facebook/react/issues/1471
HoldOffHunger
42

Comme vous pouvez le voir dans cet exemple: 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);
});

les événements clicket changesont déclenchés lors de la sélection d'une option de bouton radio (au moins dans certains navigateurs).

Je dois également souligner que dans mon exemple l' clickévénement est toujours déclenché lorsque vous utilisez l'onglet et le clavier pour sélectionner une option.

Donc, mon point est que même si l' changeévénement est déclenché dans certains navigateurs, l' clickévénement doit fournir la couverture dont vous avez besoin.

Philip Walton
la source
6
Oui, car il y a une console.logdéclaration dans mon code, que IE7 ne prend pas en charge. Vous pouvez simplement l'alerter dans IE si vous le souhaitez.
Philip Walton
Merci. Cela ne traite pas de la façon d'obtenir la case à cocher précédemment sélectionnée. Merci également, je ne savais pas que console.log ne fonctionnait pas dans IE.
Matthew
Ne doublez pas les gestionnaires d'événements - dans les navigateurs qui déclenchent à la fois les gestionnaires d'événements clicket change, vous finirez par appeler le gestionnaire deux fois. Dans ce cas, puisque @Matthew est concerné par la valeur précédente, cela pourrait entraîner de mauvaises conséquences.
Nate Cook
3
@NateCook vous avez clairement manqué le point de mon exemple. Je montrais que chaque fois que l'événement de modification est déclenché, l'événement de clic est également déclenché. Ce n'est pas parce que j'utilisais les deux événements dans mon exemple que j'en faisais la promotion. Je pense que votre vote défavorable n'était pas mérité.
Philip Walton
Mais vous en faisiez la promotion - votre réponse initiale disait "Donc, mon point est que même si l'événement de modification est déclenché dans certains navigateurs, l'événement de clic doit fournir la couverture dont vous avez besoin comme solution de secours, et vous pouvez utiliser la modification dans les navigateurs. qui le soutiennent. " clickest le bon gestionnaire ici et le seul dont vous avez besoin. Votre révision clarifie cela, donc je supprime mon vote défavorable.
Nate Cook
10

Qu'en est-il de l'utilisation de l'événement de changement de 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/

Razan Paul
la source
$(this).val()peut également être remplacé par du javascript natif e.currentTarget.value, où e est l'objet d'événement transmis via la fonction de rappel.
Eric
6

Comme vous pouvez le voir ici: http://www.w3schools.com/jsref/event_onchange.asp L'attribut onchange n'est pas pris en charge pour les boutons radio.

La première question SO liée par vous vous donne la réponse: utilisez onclickplutôt l' événement et vérifiez l'état du bouton radio à l'intérieur de la fonction qu'il déclenche.

Constantin Groß
la source
C'est juste un peu incomplet. Alors, après avoir créé une fonction pour gérer tous les clics dans le groupe, comment vérifieriez-vous lequel a été désélectionné? Aussi, je recherche une solution non jquery.
Matthieu
Le bouton radio cliqué sera coché, tous les autres du même groupe seront décochés. Ou, vous pouvez parcourir tous les boutons radio de ce groupe et vérifier leur statut. Si vous avez fourni plus d'informations sur ce que vous voulez faire avec les boutons radio, il serait plus facile de vous dire comment procéder.
Constantin Groß
2
onclickn'est pas la même sémantique, car vous pouvez modifier la vérification d'un bouton radio via l'entrée au clavier, étant donné que la sélection de la forme du clavier est activée.
gsnedders
@gsnedders onclick semble fonctionner via la saisie au clavier dans la plupart des navigateurs - Firefox, IE, Safari, Chrome. Il est étrange qu'il fasse ce que l'onchange est censé faire, mais il le fait. Je suis cependant curieux de savoir comment cela fonctionne sur les plates-formes mobiles.
Matthieu
1
w3schools pour 1 et n'a pas résolu tout le problème pour 2 qui était de savoir comment obtenir la radio précédemment sélectionnée. C'était la partie la plus importante de la question dans mon esprit.
Matthieu
6

Je ne pense pas qu'il y ait d'autre moyen que de stocker l'état précédent. Voici la solution avec 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" />

Après y avoir réfléchi un peu plus, j'ai décidé de me débarrasser de la variable et d'ajouter / supprimer une classe. Voici ce que j'ai obtenu: http://jsfiddle.net/BeQh3/2/

Alex Okrushko
la source
1
J'ai pensé à utiliser un jQuery et il y a certainement beaucoup plus à faire avec. Vous pouvez lier certains événements personnalisés pour les vérifications et les décoches et même vérifier les bizarreries entre navigateurs. Cela semble être une bonne idée pour un plugin.
Matthieu
Merci. J'aime jQuery mais il m'est indisponible dans ce cas.
Matthew
Comment jQuery est-il indisponible pour vous?
jmort253
1
Si jQuery n'était pas disponible pour moi, je trouverais un autre travail.
Adrian Carr
5

Oui, il n'y a pas d'événement de modification pour le bouton radio actuellement sélectionné. Mais le problème est que chaque bouton radio est considéré comme un élément distinct. Au lieu de cela, un groupe radio devrait être considéré comme un élément unique comme select. L'événement de changement est donc déclenché pour ce groupe. Si c'est unselect élément, nous ne nous soucions jamais de chaque option, mais ne prenons que l'option sélectionnée. Nous stockons la valeur actuelle dans une variable qui deviendra la valeur précédente, lorsqu'une nouvelle option est sélectionnée. De même, vous devez utiliser une variable distincte pour stocker la valeur du bouton radio coché.

Si vous souhaitez identifier le bouton radio précédent, vous devez boucler sur l' mousedownévénement.

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

voir ceci: http://jsfiddle.net/diode/tywx6/2/

Diode
la source
J'ai pensé à utiliser mousedown pour vérifier avant le clic, mais cela ne fonctionnera pas lorsque vous utilisez l'espace pour sélectionner la radio. Peut-être l'événement de mise au point à la place ou en plus de ce que vous avez mentionné.
Matthew le
5

Stockez la radio précédemment vérifiée dans une 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);

CODE EXEMPLE JS

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);
Dimitar Bonev
la source
Merci. Je pourrais pousser le violon encore un peu plus loin et ranger la radio elle-même. De cette façon, lorsque la valeur change, vous avez une référence à la radio précédemment sélectionnée plutôt que simplement sa valeur.
Matthieu
@Matthew En fait, le violon que j'ai partagé stockait l'élément radio et pas seulement la valeur. La valeur a été enregistrée pour montrer le but du code, mais elle n'a pas été stockée pour une utilisation ultérieure. J'édite les noms des variables pour être plus clarifiés: previousChecked -> previousCheckedRadio, that -> currentCheckedRadio;
Dimitar Bonev
Merci. C'est une bonne solution, sauf pour utiliser l'événement de modification qui ne se comporte pas correctement entre les navigateurs. Si vous utilisiez le clic à la place, ce serait mieux.
Matthew
5

Je me rends compte que c'est un vieux problème, mais cet extrait de code fonctionne pour moi. Peut-être que quelqu'un dans le futur le trouvera utile:

<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>
John K
la source
1
Si vous ajoutez, onkeydown="radioChange('juju','button1',radioArray);"vous pouvez également capturer lorsqu'un utilisateur utilise de l'espace pour vérifier la radio.
Matthew le
2

C'est juste par dessus ma tête, mais vous pouvez faire un événement onClick pour chaque bouton radio, leur donner tous les ID différents, puis faire une boucle for dans l'événement pour parcourir chaque bouton radio du groupe et trouver lequel est a été vérifié en regardant l'attribut «vérifié». L'identifiant de la variable cochée serait stocké en tant que variable, mais vous voudrez peut-être d'abord utiliser une variable temporaire pour vous assurer que la valeur de cette variable a changé, car l'événement de clic se déclencherait, qu'un nouveau bouton radio soit coché ou non.

Andrew Latham
la source
2
<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>
umesh unnikrishnan
la source
2

Si vous souhaitez éviter les scripts en ligne, vous pouvez simplement écouter un événement de clic sur la radio. Cela peut être réalisé avec du Javascript brut en écoutant un événement de clic sur

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);
      }
}
mareks
la source
2

Vous pouvez ajouter le script JS suivant

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

cela fonctionne pour moi

<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>
Doberon
la source
Je pense que cela devrait être la réponse maintenant qu'elle est soutenue.
Leo
0

C'est la fonction la plus simple et la plus efficace à utiliser, il suffit d'ajouter autant de boutons que vous le souhaitez à la case cochée = false et de faire en sorte que l'événement onclick de chaque bouton radio appelle cette fonction. Désignez un numéro unique pour chaque bouton radio

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

Manière la plus simple et la plus puissante

lecture seule des entrées radio à l'aide de getAttribute

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

if(e.target.getAttribute('name')=="myRadios")
console.log(e.target.value)
})
<input type="text"  value="iam text" /> 
<input type="radio" name="myRadios" value="1" /> 1
<input type="radio" name="myRadios" value="2" /> 2

ßãlãjî
la source