Der OnChange-Ereignishandler für das Optionsfeld (INPUT type = "radio") funktioniert nicht als ein Wert

190

Ich suche eine allgemeine Lösung dafür.

Betrachten Sie 2 gleichnamige Funkeingänge. Bei der Übermittlung bestimmt der geprüfte Wert den Wert, der mit dem Formular gesendet wird:

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

Das Änderungsereignis wird nicht ausgelöst, wenn ein Optionsfeld deaktiviert ist. Wenn also das Radio mit dem Wert = "1" bereits ausgewählt ist und der Benutzer das zweite auswählt, wird handleChange1 () nicht ausgeführt. Dies stellt (für mich jedenfalls) ein Problem dar, da es kein Ereignis gibt, bei dem ich diese Abwahl abfangen kann.

Was ich möchte, ist eine Problemumgehung für das Ereignis onchange für den Wert der Kontrollkästchengruppe oder alternativ ein Ereignis oncheck, das nicht nur erkennt, wenn ein Radio aktiviert ist, sondern auch, wenn es deaktiviert ist.

Ich bin sicher, einige von Ihnen sind schon einmal auf dieses Problem gestoßen. Was sind einige Problemumgehungen (oder idealerweise der richtige Weg, um damit umzugehen)? Ich möchte nur das Änderungsereignis abfangen, auf das zuvor überprüfte Radio sowie auf das neu überprüfte Radio zugreifen.

PS
onclick scheint ein besseres (browserübergreifendes) Ereignis zu sein, um anzuzeigen, wann ein Radio überprüft wird, aber das nicht überprüfte Problem wird immer noch nicht gelöst.

Ich nehme an, es ist sinnvoll, warum das Ändern eines Kontrollkästchentyps in einem solchen Fall funktioniert, da es den Wert ändert, den es beim Aktivieren oder Deaktivieren des Kontrollkästchens übermittelt. Ich wünschte, die Optionsfelder hätten sich eher wie die Änderung eines SELECT-Elements verhalten, aber was können Sie tun ...

Matthew
quelle

Antworten:

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>

Hier ist eine JSFiddle-Demo: https://jsfiddle.net/crp6em1z/

Michal
quelle
4
Nur ein Hinweis, warum ich dies als richtige Antwort gewählt habe: Auf jedem Optionsfeld werden Klickereignishandler mit dem Attribut name eingerichtet myRadios, um die Variable zu lesen, prevdie das aktuell ausgewählte Radio enthält. In jedem Klick-Handler wird ein Vergleich durchgeführt, um zu entscheiden, ob das angeklickte Radio mit dem darin gespeicherten identisch ist. prevWenn nicht, wird das aktuell angeklickte Radio dort gespeichert. Innerhalb des Klick-Handlers haben Sie Zugriff auf das zuvor ausgewählte: prevund das aktuell ausgewählte Radio:this
Matthew
26
Es ist besser, die Funktion außerhalb der Schleife zwischenzuspeichern, damit alle Funkgeräte denselben Ereignishandler verwenden (jetzt haben sie identische Handler, aber sie sind unterschiedliche Funktionen). Oder legen Sie alle Radios in einen Wrapper und verwenden Sie die Ereignisdelegation
Oriol
1
@Oriol oder jemand, der sich auskennt, können Sie ein Beispiel für (1) Caching außerhalb der Schleife oder (2) Wrapper + Ereignisdelegation geben?
Matt Voda
14
onclick funktioniert nicht mit der Tastaturauswahl, die Sie verwenden können, rad[i].addEventListener('change', function(){ //your handler code })und es funktioniert sowohl für die Maus als auch für die Tastatur
Juanmi Rodriguez
117

Ich würde zwei Änderungen vornehmen:

<input type="radio" name="myRadios" onclick="handleClick(this);" value="1" />
<input type="radio" name="myRadios" onclick="handleClick(this);" value="2" />
  1. Verwenden Sie onclickstattdessen den Handler onchange- Sie ändern den "geprüften Status" des Funkeingangs, nicht den value, sodass kein Änderungsereignis auftritt.
  2. Verwenden Sie eine einzelne Funktion und übergeben Sie sie thisals Parameter, um zu überprüfen, welcher Wert aktuell ausgewählt ist.

ETA: Zusammen mit Ihrer handleClick()Funktion können Sie den ursprünglichen / alten Wert des Radios in einer Variablen mit Seitenbereich verfolgen. Das ist:

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
quelle
Vielen Dank, obwohl dies nicht das Problem behebt, dass das zuvor überprüfte Radio abgerufen werden muss, und Sie auch etwas angeben, das andere Benutzer bereits erwähnt haben, nämlich "onclick" anstelle von "onchange" zu verwenden. Eigentlich wusste ich das von Anfang an, aber ich wollte darauf aufmerksam machen, dass onchange nicht wie erwartet funktioniert und ich würde gerne besser damit umgehen.
Matthew
1
Sie verwenden JavaScript, richtig? Warum also nicht einfach eine Variable pflegen, in der das zuletzt bekannte ausgewählte Optionsfeld gespeichert ist? Wenn Sie einen einzelnen Handler verwenden, können Sie diesen gespeicherten Wert überprüfen, bevor Sie ihn mit dem neuen Wert überschreiben. +1
jmort253
13
@Matthew: Der onclickHandler ist nur schlecht benannt - er behandelt das Ereignis der Auswahl von Optionsfeldern, unabhängig davon, ob die Schaltfläche durch Drücken der Eingabetaste auf einer Tastatur angeklickt, berührt oder aktiviert wird. Der onchangeHandler ist in diesem Fall nicht geeignet, da sich der Wert der Eingabe nicht ändert, sondern nur das aktivierte / nicht aktivierte Attribut. Ich habe ein Beispielskript hinzugefügt, um den vorherigen Wert zu adressieren.
Nate Cook
1
"onClick" behandelt das Ereignis nicht, wenn der Benutzer die Tastatur (Tab + Leertaste) zur Auswahl des Radios verwendet hat (und dies ist bei großen Formularen üblich).
HoldOffHunger
+1. "onChange ()" ist kein auslösbares Ereignis in ReactJS und dies ist die einzige Lösung. Quelle: github.com/facebook/react/issues/1471
HoldOffHunger
42

Wie Sie diesem Beispiel entnehmen können: entnehmen 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);
});

sowohl die clickals auchchange Ereignisse werden ausgelöst, wenn eine Optionsfeldoption ausgewählt wird (zumindest in einigen Browsern).

Ich sollte auch darauf hinweisen, dass in meinem Beispiel das clickEreignis immer noch ausgelöst wird wenn Sie mit Tab und Tastatur eine Option auswählen.

Mein Punkt ist also, dass, obwohl das changeEreignis in einigen Browsern ausgelöst wird, das clickEreignis die Abdeckung bieten sollte, die Sie benötigen.

Philip Walton
quelle
6
Ja, da console.logmein Code eine Anweisung enthält, die IE7 nicht unterstützt. Sie können es einfach im IE alarmieren, wenn Sie möchten.
Philip Walton
Vielen Dank. Hier wird jedoch nicht behandelt, wie das zuvor ausgewählte Kontrollkästchen abgerufen werden soll. Danke auch, ich wusste nicht, dass console.log im IE nicht funktioniert.
Matthew
Verdoppeln Sie nicht auf Event - Handler - in Browsern , dass Feuer sowohl die clickund changeEvent - Handler, werden Sie den Handler zweimal Aufruf enden. In diesem Fall kann dies zu schlechten Konsequenzen führen, da sich @Matthew mit dem vorherigen Wert befasst.
Nate Cook
3
@NateCook du hast den Punkt meines Beispiels deutlich verfehlt. Ich habe gezeigt, dass jedes Mal, wenn das Änderungsereignis ausgelöst wird, auch das Klickereignis ausgelöst wird. Nur weil ich in meinem Beispiel beide Ereignisse verwendet habe, heißt das nicht, dass ich dafür geworben habe. Ich denke, Ihre Ablehnung war unverdient.
Philip Walton
Aber Sie haben es beworben - Ihre ursprüngliche Antwort lautete: "Mein Punkt ist also, dass das Klickereignis, obwohl das Änderungsereignis bei einigen Browsern ausgelöst wird, die Abdeckung liefern sollte, die Sie als Ersatz benötigen, und Sie können Änderungen in den Browsern verwenden." das unterstützt es. " clickist hier der richtige Handler und der einzige, den Sie brauchen. Ihre Überarbeitung verdeutlicht dies, daher entferne ich meine Ablehnung.
Nate Cook
10

Was ist mit dem Änderungsereignis von 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
quelle
$(this).val()kann auch durch natives Javascript ersetzt werden e.currentTarget.value, wobei e das Ereignisobjekt ist, das durch die Rückruffunktion übergeben wird.
Eric
6

Wie Sie hier sehen können: http://www.w3schools.com/jsref/event_onchange.asp Das Attribut onchange wird für Optionsfelder nicht unterstützt.

Die erste von Ihnen verknüpfte SO-Frage gibt Ihnen die Antwort: Verwenden Sie onclickstattdessen das Ereignis und überprüfen Sie den Optionsfeldstatus innerhalb der von ihm ausgelösten Funktion.

Constantin Groß
quelle
Dies ist nur ein bisschen unvollständig. Wie würden Sie nach dem Erstellen einer Funktion zur Verarbeitung aller Klicks in der Gruppe überprüfen, welche abgewählt wurde? Außerdem suche ich nach einer Non-JQuery-Lösung.
Matthew
Das angeklickte Optionsfeld wird aktiviert, alle anderen Mitglieder derselben Gruppe werden deaktiviert. Oder Sie können alle Optionsfelder dieser Gruppe durchlaufen und ihren Status überprüfen. Wenn Sie weitere Informationen darüber bereitstellen, was Sie mit den Optionsfeldern tun möchten, ist es einfacher, Ihnen zu sagen, wie Sie fortfahren sollen.
Constantin Groß
2
onclickist nicht dieselbe Semantik, da Sie die Überprüfbarkeit eines Optionsfelds durch Tastatureingabe ändern können, wenn die Auswahl der Tastaturform aktiviert ist.
Gsnedders
@gsnedders onclick scheint jedoch in den meisten Browsern über Tastatureingaben zu funktionieren - Firefox, IE, Safari, Chrome. Es ist seltsam, dass es das tut, was onchange tun soll, aber es tut es. Ich bin gespannt, wie das auf mobilen Plattformen funktioniert.
Matthew
1
w3schools for 1 und hat nicht das ganze Problem für 2 angesprochen, wie man das zuvor ausgewählte Radio bekommt. 2 war für mich der wichtigste Teil der Frage.
Matthew
6

Ich glaube nicht, dass es eine andere Möglichkeit gibt, als den vorherigen Status zu speichern. Hier ist die Lösung mit 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" />

Nachdem ich ein bisschen mehr darüber nachgedacht hatte, beschloss ich, die Variable loszuwerden und die Klasse hinzuzufügen / zu entfernen. Folgendes habe ich bekommen: http://jsfiddle.net/BeQh3/2/

Alex Okrushko
quelle
1
Ich habe über die Verwendung einer jQuery nachgedacht und es gibt definitiv noch viel mehr, was damit gemacht werden könnte. Sie können einige benutzerdefinierte Ereignisse für aktivierte und deaktivierte Elemente binden und sogar nach browserübergreifenden Macken suchen. Klingt nach einer guten Idee für ein Plugin.
Matthew
Vielen Dank. Ich mag jQuery, aber es ist in diesem Fall für mich nicht verfügbar.
Matthew
Wie ist jQuery für Sie nicht verfügbar?
jmort253
1
Wenn jQuery für mich nicht verfügbar wäre, würde ich einen anderen Job finden.
Adrian Carr
5

Ja, es gibt kein Änderungsereignis für das aktuell ausgewählte Optionsfeld. Das Problem ist jedoch, wenn jedes Optionsfeld als separates Element verwendet wird. Stattdessen sollte eine Funkgruppe als ein einzelnes Element betrachtet werden select. Daher wird für diese Gruppe ein Änderungsereignis ausgelöst. Wenn es ein istselect Element handelt, kümmern wir uns nie um jede Option, sondern nehmen nur die ausgewählte Option. Wir speichern den aktuellen Wert in einer Variablen, die zum vorherigen Wert wird, wenn eine neue Option ausgewählt wird. Ebenso müssen Sie eine separate Variable zum Speichern des Werts des aktivierten Optionsfelds verwenden.

Wenn Sie das vorherige Optionsfeld identifizieren möchten, müssen Sie das mousedownEreignis wiederholen .

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

siehe dies: http://jsfiddle.net/diode/tywx6/2/

Diode
quelle
Ich habe darüber nachgedacht, Mousedown zu verwenden, um zu überprüfen, bevor das Klicken passiert ist, aber das funktioniert nicht, wenn Sie Platz für die Auswahl des Radios verwenden. Vielleicht das Fokusereignis anstelle oder zusätzlich zu dem, was Sie erwähnt haben.
Matthew
5

Speichern Sie das zuvor überprüfte Radio in einer Variablen:
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 BEISPIELCODE

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
quelle
Vielen Dank. Ich könnte die Geige noch ein bisschen weiter gehen und das Radio selbst aufbewahren. Auf diese Weise haben Sie, wenn sich der Wert ändert, einen Verweis auf das zuvor ausgewählte Radio und nicht nur auf dessen Wert.
Matthew
@Matthew Eigentlich war die Geige, die ich geteilt habe, das Speichern des Radio-Elements und nicht nur des Werts. Der Wert wurde protokolliert, um den Zweck des Codes anzuzeigen, wurde jedoch nicht für die spätere Verwendung gespeichert. Ich bearbeite die Variablennamen, um mehr Klarheit zu erhalten: previousChecked -> previousCheckedRadio, that -> currentCheckedRadio;
Dimitar Bonev
Vielen Dank. Dies ist eine gute Lösung, außer dass das Änderungsereignis verwendet wird, das sich browserübergreifend nicht richtig verhält. Wenn Sie stattdessen Klick verwenden, ist es besser.
Matthew
5

Mir ist klar, dass dies ein altes Problem ist, aber dieser Codeausschnitt funktioniert für mich. Vielleicht wird es jemand in Zukunft nützlich finden:

<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.
quelle
1
Wenn Sie hinzufügen, können onkeydown="radioChange('juju','button1',radioArray);"Sie auch erfassen, wenn ein Benutzer Speicherplatz zum Überprüfen des Radios verwendet.
Matthew
2

Dies ist mir ein Rätsel, aber Sie können für jedes Optionsfeld ein onClick-Ereignis durchführen, ihnen alle unterschiedlichen IDs geben und dann eine for-Schleife im Ereignis erstellen, um jedes Optionsfeld in der Gruppe zu durchlaufen und herauszufinden, welches ist wurde durch Betrachten des Attributs 'geprüft' überprüft. Die ID der aktivierten Variable wird als Variable gespeichert. Möglicherweise möchten Sie jedoch zuerst eine temporäre Variable verwenden, um sicherzustellen, dass sich der Wert dieser Variablen geändert hat, da das Klickereignis auslösen würde, ob ein neues Optionsfeld aktiviert wurde oder nicht.

Andrew Latham
quelle
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
quelle
2

Wenn Sie Inline-Skripte vermeiden möchten, können Sie einfach im Radio auf ein Klickereignis warten. Dies kann mit einfachem Javascript erreicht werden, indem ein Klickereignis angehört wird

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
quelle
2

Sie können das folgende JS-Skript hinzufügen

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

das funktioniert bei mir

<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
quelle
Ich denke, dies sollte die Antwort sein, jetzt wo es unterstützt wird.
Leo
0

Dies ist die einfachste und effizienteste Funktion, mit der Sie einfach so viele Schaltflächen hinzufügen können, wie Sie möchten. Aktivieren Sie das Kontrollkästchen = false und lassen Sie das Onclick-Ereignis jedes Optionsfelds diese Funktion aufrufen. Geben Sie jedem Optionsfeld eine eindeutige Nummer an

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

Am einfachsten und kraftvollsten

schreibgeschützte Funkeingänge mit 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î
quelle