Handler event OnChange untuk tombol radio (INPUT type = "radio") tidak berfungsi sebagai satu nilai

191

Saya mencari solusi umum untuk ini.

Pertimbangkan 2 input jenis radio dengan nama yang sama. Saat dikirimkan, yang diperiksa menentukan nilai yang dikirim dengan formulir:

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

Acara perubahan tidak menyala ketika tombol radio tidak dipilih. Jadi jika radio dengan nilai = "1" sudah dipilih dan pengguna memilih yang kedua, handleChange1 () tidak berjalan. Ini menghadirkan masalah (bagi saya toh) karena tidak ada peristiwa di mana saya dapat menangkap seleksi-de ini.

Apa yang saya inginkan adalah solusi untuk acara onchange untuk nilai grup kotak centang atau sebagai alternatif aktivitas oncheck yang mendeteksi tidak hanya ketika radio dicentang tetapi juga saat tidak dicentang.

Saya yakin beberapa dari Anda pernah mengalami masalah ini sebelumnya. Apa saja pemecahan masalah (atau idealnya apa cara yang tepat untuk menangani ini)? Saya hanya ingin menangkap perubahan acara, mengakses radio yang sebelumnya diperiksa serta radio yang baru diperiksa.

PS
onclick sepertinya acara (lintas-peramban) yang lebih baik untuk menunjukkan kapan radio diperiksa tetapi masih tidak menyelesaikan masalah yang tidak dicentang.

Saya kira masuk akal mengapa pertukaran untuk jenis kotak centang tidak berfungsi dalam kasus seperti ini karena ini mengubah nilai yang dikirimkan ketika Anda memeriksa atau tidak mencentangnya. Saya berharap tombol radio berperilaku lebih seperti pertukaran elemen SELECT tetapi apa yang dapat Anda lakukan ...

Matius
sumber

Jawaban:

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>

Berikut ini demo JSFiddle: https://jsfiddle.net/crp6em1z/

Michal
sumber
4
Hanya sebuah catatan mengapa saya memilih ini sebagai jawaban yang benar: Klik pengendali acara diatur pada masing-masing tombol radio dengan atribut nama myRadiosuntuk membaca variabel prevyang memegang radio yang saat ini dipilih. Perbandingan dilakukan di dalam setiap penangan klik untuk memutuskan apakah radio yang diklik sama dengan yang disimpan prevdan jika tidak, radio yang saat ini diklik disimpan di sana. Di dalam pengendali klik, Anda memiliki akses ke prevradio yang sebelumnya dipilih: dan radio yang saat ini dipilih:this
Matius
26
Akan lebih baik untuk men-cache fungsi di luar loop, sehingga semua radio berbagi event handler yang sama (sekarang mereka memiliki penangan yang identik tetapi mereka memiliki fungsi yang berbeda). Atau mungkin memasukkan semua radio ke dalam pembungkus dan menggunakan delegasi acara
Oriol
1
@Oriol, atau siapa pun yang berpengetahuan luas, dapatkah Anda memberikan contoh (1) caching di luar loop atau (2) pembungkus + delegasi acara?
Matt Voda
14
onclick tidak bekerja dengan pemilihan keyboard, Anda dapat menggunakan rad[i].addEventListener('change', function(){ //your handler code })dan itu akan bekerja untuk mouse dan keyboard
Juanmi Rodriguez
117

Saya akan membuat dua perubahan:

<input type="radio" name="myRadios" onclick="handleClick(this);" value="1" />
<input type="radio" name="myRadios" onclick="handleClick(this);" value="2" />
  1. Gunakan onclickhandler alih-alih onchange- Anda mengubah "status dicentang" dari input radio, bukan value, jadi tidak ada perubahan yang terjadi.
  2. Gunakan fungsi tunggal, dan lulus thissebagai parameter, yang akan memudahkan untuk memeriksa nilai mana yang saat ini dipilih.

ETA: Seiring dengan handleClick()fungsi Anda, Anda dapat melacak nilai asli / lama radio dalam variabel cakupan halaman. Itu adalah:

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
sumber
Terima kasih, meskipun ini tidak membahas masalah harus mendapatkan radio yang diperiksa sebelumnya dan Anda juga menyatakan sesuatu yang telah disebutkan pengguna lain yang menggunakan "onclick" daripada "onchange". Saya sebenarnya tahu ini dari awal tetapi saya ingin menarik perhatian pada kenyataan bahwa pertukaran tidak berfungsi seperti yang diharapkan dan saya ingin menanganinya dengan lebih baik.
Matius
1
Anda menggunakan JavaScript, bukan? Jadi mengapa tidak mempertahankan variabel yang menyimpan tombol radio terpilih yang terakhir diketahui? Jika Anda menggunakan penangan tunggal, maka Anda dapat memeriksa nilai yang disimpan ini sebelum Anda menimpanya dengan nilai yang baru. +1
jmort253
13
@ Matthew: onclickPawang hanya bernama buruk - menangani acara pemilihan tombol radio apakah tombol diklik, disentuh, atau diaktifkan dengan menekan "enter" pada keyboard. The onchangehandler tidak yang sesuai dalam kasus ini karena nilai input tidak berubah, hanya diperiksa / atribut dicentang. Saya telah menambahkan contoh skrip untuk mengatasi nilai sebelumnya.
Nate Cook
1
"onClick" tidak akan menangani acara jika pengguna menggunakan keyboard (tab + bilah spasi) untuk memilih radio (dan ini adalah praktik umum pada formulir besar).
HoldOffHunger
+1. "onChange ()" bukan acara yang bisa dipecat di ReactJS dan ini adalah satu-satunya solusi. Sumber: github.com/facebook/react/issues/1471
HoldOffHunger
42

Seperti yang Anda lihat dari contoh ini: 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);
});

baik acara clickdan changedipecat ketika memilih opsi tombol radio (setidaknya di beberapa browser).

Saya juga harus menunjukkan bahwa dalam contoh saya clickacara masih dipecat ketika Anda menggunakan tab dan keyboard untuk memilih opsi.

Jadi, maksud saya adalah bahwa meskipun changeacara dipecat adalah beberapa browser, clickacara tersebut harus menyediakan cakupan yang Anda butuhkan.

Philip Walton
sumber
6
Ya, karena ada console.logpernyataan dalam kode saya, yang tidak didukung IE7. Anda bisa memberitahukannya di IE jika Anda mau.
Philip Walton
Terima kasih. Ini tidak membahas bagaimana cara mendapatkan kotak centang yang dipilih sebelumnya. Juga terima kasih, saya tidak tahu console.log tidak berfungsi di IE.
Matius
Jangan gandakan pada penangan event - di browser yang memecat penangan event clickdan change, Anda akhirnya akan memanggil penangan dua kali. Dalam hal ini, karena @Matthew berkaitan dengan nilai sebelumnya, yang dapat menyebabkan konsekuensi buruk.
Nate Cook
3
@NateCook Anda jelas melewatkan poin dari contoh saya. Saya menunjukkan bahwa setiap kali acara perubahan diaktifkan, acara klik juga diaktifkan. Hanya karena saya menggunakan kedua acara dalam contoh saya tidak berarti saya mempromosikannya. Saya pikir suara Anda tidak pantas.
Philip Walton
Tapi Anda mempromosikannya - jawaban awal Anda mengatakan, "Jadi, maksud saya adalah bahwa meskipun acara perubahan dipecat adalah beberapa browser, acara klik harus menyediakan cakupan yang Anda butuhkan sebagai mundur, dan Anda dapat menggunakan perubahan di browser. yang mendukungnya. " clickadalah penangan yang benar di sini dan satu-satunya yang Anda butuhkan. Revisi Anda mengklarifikasi itu, jadi saya menghapus suara pilihan saya.
Nate Cook
10

Bagaimana dengan menggunakan acara perubahan 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
sumber
$(this).val()juga bisa diganti dengan javascript asli e.currentTarget.value, di mana e adalah objek acara yang melewati fungsi panggilan balik.
Eric
6

Seperti yang Anda lihat di sini: http://www.w3schools.com/jsref/event_onchange.asp Atribut onchange tidak didukung untuk tombol radio.

Pertanyaan SO pertama yang ditautkan oleh Anda memberi Anda jawabannya: Gunakan onclickacara itu dan periksa status tombol radio di dalam fungsi yang dipicunya.

Constantin Groß
sumber
Ini hanya sedikit tidak lengkap. Jadi, setelah membuat fungsi untuk menangani semua klik dalam grup, bagaimana Anda memeriksa untuk melihat mana yang telah dipilih? Juga, saya mencari solusi non-jquery.
Matius
Tombol radio yang diklik akan diperiksa, semua yang lain dari grup yang sama akan dicentang. Atau, Anda dapat memutar semua tombol radio dari grup itu dan memeriksa statusnya. Jika Anda memberikan informasi lebih lanjut tentang apa yang ingin Anda lakukan dengan tombol radio, akan lebih mudah untuk memberi tahu Anda bagaimana cara melanjutkannya.
Constantin Groß
2
onclickbukan semantik yang sama, karena Anda dapat mengubah ketelitian tombol radio melalui input keyboard mengingat pemilihan bentuk keyboard diaktifkan.
gsnedders
@gsnedders onclick tampaknya berfungsi melalui input keyboard di sebagian besar browser - Firefox, IE, Safari, Chrome. Aneh bahwa ia melakukan apa yang seharusnya dilakukan oleh pertukaran, tetapi ia melakukannya. Saya ingin tahu bagaimana ini bekerja pada platform seluler.
Matius
1
w3sekolah untuk 1 dan tidak membahas seluruh masalah untuk 2 yang merupakan cara untuk mendapatkan radio yang dipilih sebelumnya. 2 adalah bagian terpenting dari pertanyaan di benak saya.
Matius
6

Saya tidak berpikir ada cara lain selain menyimpan keadaan sebelumnya. Ini solusinya dengan 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" />

Setelah memikirkannya sedikit lebih banyak, saya memutuskan untuk menyingkirkan variabel dan menambah / menghapus kelas. Inilah yang saya dapatkan: http://jsfiddle.net/BeQh3/2/

Alex Okrushko
sumber
1
Saya berpikir tentang menggunakan jQuery dan pasti ada banyak lagi yang bisa dilakukan dengan itu. Anda dapat mengikat beberapa acara khusus untuk dicentang dan tidak dicentang dan bahkan memeriksa quirks lintas browser. Kedengarannya ide yang bagus untuk sebuah plugin.
Matius
Terima kasih. Saya suka jQuery tetapi tidak tersedia untuk saya dalam kasus ini.
Matius
Bagaimana jQuery tidak tersedia untuk Anda?
jmort253
1
Jika jQuery tidak tersedia untuk saya, saya akan menemukan pekerjaan yang berbeda.
Adrian Carr
5

Ya tidak ada perubahan acara untuk tombol radio yang dipilih saat ini. Tetapi masalahnya adalah ketika setiap tombol radio diambil sebagai elemen yang terpisah. Sebagai gantinya grup radio harus dianggap sebagai elemen tunggal select. Jadi perubahan acara dipicu untuk grup itu. Jika itu adalah selectelemen, kami tidak pernah khawatir tentang setiap opsi di dalamnya, tetapi hanya mengambil opsi yang dipilih. Kami menyimpan nilai saat ini dalam variabel yang akan menjadi nilai sebelumnya, ketika opsi baru dipilih. Demikian pula Anda harus menggunakan variabel terpisah untuk menyimpan nilai tombol radio yang diperiksa.

Jika Anda ingin mengidentifikasi tombol radio sebelumnya, Anda harus mengulang mousedownacara.

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

lihat ini: http://jsfiddle.net/diode/tywx6/2/

Diode
sumber
Saya berpikir tentang menggunakan mousedown untuk memeriksa sebelum klik terjadi tetapi itu tidak akan berfungsi ketika menggunakan ruang untuk memilih radio. Mungkin acara fokus di tempat atau di samping apa yang Anda sebutkan.
Matius
5

Simpan radio yang diperiksa sebelumnya dalam sebuah variabel:
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);

KODE CONTOH 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
sumber
Terima kasih. Saya mungkin mengambil biola sedikit lebih jauh dan menyimpan radio itu sendiri. Dengan cara ini ketika nilainya berubah, Anda memiliki referensi ke radio yang dipilih sebelumnya dan bukan hanya nilainya saja.
Matius
@ Matthew Sebenarnya biola yang saya bagikan adalah menyimpan elemen radio dan bukan nilai saja. Nilai dicatat untuk menunjukkan tujuan kode tetapi tidak disimpan untuk penggunaan nanti. Saya mengedit nama variabel untuk menjadi lebih jelas: priorChecked -> beforeCheckedRadio, itu -> currentCheckedRadio;
Dimitar Bonev
Terima kasih. Ini adalah solusi yang baik kecuali untuk menggunakan acara perubahan yang tidak berperilaku lintas-browser dengan benar. Jika Anda menggunakan klik, itu akan lebih baik.
Matius
5

Saya menyadari ini adalah masalah lama, tetapi potongan kode ini cocok untuk saya. Mungkin seseorang di masa depan akan merasakan manfaatnya:

<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.
sumber
1
Jika Anda menambahkan, onkeydown="radioChange('juju','button1',radioArray);"Anda juga bisa menangkap ketika pengguna menggunakan ruang untuk memeriksa radio.
Matius
2

Ini tepat di atas kepala saya, tetapi Anda bisa melakukan acara onClick untuk setiap tombol radio, berikan semua ID yang berbeda, dan kemudian buat loop untuk acara tersebut melalui setiap tombol radio dalam grup dan temukan yang mana diperiksa dengan melihat atribut 'diperiksa'. Id dari yang dicentang akan disimpan sebagai variabel, tetapi Anda mungkin ingin menggunakan variabel temp terlebih dahulu untuk memastikan bahwa nilai variabel itu berubah, karena acara klik akan menyala apakah tombol radio baru diperiksa atau tidak.

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

Jika Anda ingin menghindari skrip inline, Anda cukup mendengarkan acara klik di radio. Ini dapat dicapai dengan Javascript biasa dengan mendengarkan acara klik pada

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

Anda dapat menambahkan skrip JS berikut

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

ini bekerja untuk saya

<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
sumber
Saya pikir ini harus menjadi jawaban sekarang karena didukung.
Leo
0

Ini adalah fungsi termudah dan paling efisien untuk digunakan, cukup tambahkan tombol sebanyak yang Anda inginkan ke tanda centang = false dan buat acara klik setiap tombol radio untuk memanggil fungsi ini. Tentukan nomor unik untuk setiap tombol radio

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

Cara termudah dan penuh daya

hanya baca input radio menggunakan 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î
sumber