单选按钮(INPUT type =“ radio”)的OnChange事件处理程序不能用作一个值


190

我正在为此寻求一个通用的解决方案。

考虑两个具有相同名称的无线电类型输入。提交后,选中的将确定以以下形式发送的值:

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

取消选择单选按钮时,更改事件不会触发。因此,如果已经选择了值=“ 1”的单选按钮,并且用户选择了第二个,则handleChange1()不会运行。这(无论如何对我而言)带来了一个问题,因为没有任何事件可以使我取消选择。

我想要的是一个针对复选框组值的onchange事件或一个oncheck事件的变通办法,该事件不仅可以检查无线电是否已选中,还可以在未选中无线电时对其进行检测。

我敢肯定你们当中有些人曾经遇到过这个问题。有哪些解决方法(或者理想情况下是正确的处理方式)?我只想捕捉更改事件,访问以前检查过的收音机以及新检查过的收音机。

PS
onclick似乎是一个更好的(跨浏览器)事件,用于指示何时选中某个收音机,但仍不能解决未选中的问题。

我认为这对于在这种情况下为什么onchange的复选框类型起作用是有道理的,因为它会更改在您选中或取消选中它时提交的值。我希望单选按钮的行为更像是SELECT元素的onchange,但是您该怎么办...

Answers:


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>

这是一个JSFiddle演示:https://jsfiddle.net/crp6em1z/


4
请注意一下我为什么选择它作为正确答案:在每个单选按钮上都设置了具有name属性的click事件处理程序,myRadios以读取prev保存当前选定单选的变量。在每个单击处理程序中进行比较,以确定被单击的收音机是否与存储在其中的收音机相同prev,如果不相同,则将当前被单击的收音机存储在此处。在点击处理程序中,您可以访问以前选择的:prev和当前选择的广播:this
Matthew

26
最好在循环外缓存该函数,以便所有无线电共享相同的事件处理程序(现在它们具有相同的处理程序,但它们是不同的功能)。或者,也许将所有收音机放在包装器中并使用事件委托
Oriol 2013年

1
@Oriol或任何有知识的人,您能否举一个例子(1)在循环外进行缓存或(2)包装器+事件委托?
马特·沃达


14
onclick不适用于键盘选择,您可以使用rad[i].addEventListener('change', function(){ //your handler code })它,并且对鼠标和键盘均适用
Juanmi Rodriguez

117

我将进行两项更改:

<input type="radio" name="myRadios" onclick="handleClick(this);" value="1" />
<input type="radio" name="myRadios" onclick="handleClick(this);" value="2" />
  1. 请使用onclick处理程序,而不要使用onchange-您要更改单选输入的“检查状态”,而不是value,因此不会发生更改事件。
  2. 使用单个函数并将其this作为参数传递,这将使检查当前选择的值变得容易。

ETA:除handleClick()功能外,您还可以在页面范围的变量中跟踪无线电的原始/旧值。那是:

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


谢谢,尽管这不能解决必须获得先前检查的单选的问题,并且您还声明了其他用户已经提到的使用“ onclick”而不是“ onchange”的内容。我实际上从一开始就知道这一点,但是我想提请注意一个事实,即onchange不能像人们期望的那样起作用,我想更好地处理它。
马修

1
您正在使用JavaScript,对吗?那么,为什么不只维护一个存储最后一个已知选定单选按钮的变量呢?如果您使用的是单个处理程序,则可以先检查此存储值,然后再用新值覆盖它。+1
jmort253

13
@Matthew:该onclick处理程序的名称不正确-通过单击键盘上的“ enter”(输入)来处理单选按钮选择的事件,无论该按钮是单击,触摸还是激活。onchange在这种情况下,该处理程序是不合适的,因为输入的值不会更改,仅更改已检查/未检查属性。我添加了一个示例脚本来解决先前的值。
Nate Cook

1
如果用户使用键盘(选项卡+空格键)选择单选按钮,则“ onClick”将不会处理该事件(这是大型表单的常见做法)。
HoldOffHunger

+1。在ReactJS中,“ onChange()”不是可触发的事件,这是唯一的解决方案。来源:github.com/facebook/react/issues/1471
HoldOffHunger '18

42

从此示例中可以看到: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);
});

无论是clickchange选择(在一些浏览器至少)单选按钮选项,当事件被触发。

我还应该指出,在我的示例中,当您使用tab和键盘选择选项时,该click事件仍会触发

因此,我的意思是,即使change事件是由某些浏览器触发的,click事件也应提供所需的覆盖范围。


6
是的,因为console.log我的代码中有一条语句,IE7不支持该语句。您可以根据需要在IE中警告它。
菲利普·沃尔顿

谢谢。但是,这没有解决如何获取先前选择的复选框。另外,谢谢,我不知道console.log在IE中不起作用。
马修(Matthew)

不要加倍使用事件处理程序-在同时触发clickchange事件处理程序的浏览器中,您将最终两次调用该处理程序。在这种情况下,由于@Matthew关注先前的值,因此可能导致严重的后果。
Nate Cook

3
@NateCook您显然错过了我的例子的重点。我向您展示的是,每当触发change事件时,也会触发click事件。仅仅因为我在示例中同时使用了这两个事件,并不意味着我在推广它。我认为你的不赞成票是不应该的。
菲利普·沃尔顿

但是您正在推广它-您的原始回答是:“所以,我的意思是,即使触发了某些浏览器的change事件,单击事件也应提供所需的覆盖范围,您可以在浏览器中使用change支持它。” click是这里的正确处理程序,也是您唯一需要的处理程序。您的修订澄清了这一点,因此我要删除我的不赞成票。
Nate Cook

10

如何使用Jquery的change事件?

$(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/


$(this).val()也可以用本机javascript替换e.currentTarget.value,其中e是通过回调函数传递的事件对象。
埃里克

6

如您所见:http : //www.w3schools.com/jsref/event_onchange.asp 单选按钮不支持onchange属性。

您链接的第一个SO问题将为您提供答案:改用该onclick事件,并检查它触发的函数内部的单选按钮状态。


这只是有点不完整。因此,在创建了一个功能来处理组中的所有点击之后,您将如何查看是否已取消选择了哪个?另外,我正在寻找一个非jQuery的解决方案。
马修

单击的单选按钮将被选中,同一组中的所有其他复选框将被取消选中。或者,您可以循环浏览该组的所有单选按钮并检查其状态。如果您提供了有关单选按钮要执行的操作的更多信息,则告诉您如何继续操作会更容易。
ConstantinGroß2012年

2
onclick是不同的语义,因为在启用键盘形式选择的情况下,您可以通过键盘输入来更改单选按钮的选中状态。
gsnedders 2012年

@gsnedders onclick似乎可以在大多数浏览器中通过键盘输入来工作-Firefox,IE,Safari,Chrome。奇怪的是,它做了onchange应该做的事情,但是确实做到了。我很好奇这在移动平台上如何工作。
马修

1
w3schools为1,并没有解决2的整个问题,即如何获得先前选择的收音机。2在我心中是问题中最重要的部分。
马修

6

我认为除了存储先前的状态之外别无其他方法。这是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" />

经过多考虑之后,我决定摆脱变量并添加/删除类。这是我得到的:http : //jsfiddle.net/BeQh3/2/


1
我考虑过使用jQuery,并且肯定还有很多可以做的事情。您可以绑定一些自定义事件以进行检查和取消检查,甚至检查跨浏览器的怪癖。听起来对插件来说是个好主意。
马修

谢谢。我喜欢jQuery,但在这种情况下无法使用。
马修

jQuery如何对您不可用?
jmort253

1
如果jQuery对我不可用,我会找到其他工作。
Adrian Carr

5

是的,当前选中的单选按钮没有更改事件。但是问题在于每个单选按钮被当作一个单独的元素时。取而代之的是,无线电组应被视为单个元素,例如select。因此,将为该组触发更改事件。如果它是一个select元素,我们就不必担心其中的每个选项,而只选择选定的选项。当选择一个新选项时,我们将当前值存储在一个变量中,该变量将成为前一个值。同样,您必须使用一个单独的变量来存储选中的单选按钮的值。

如果要标识上一个单选按钮,则必须循环mousedown事件。

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

看到这个:http : //jsfiddle.net/diode/tywx6/2/


我曾考虑过使用mousedown在点击发生之前进行检查,但是在使用空间选择收音机时这是行不通的。可能是焦点活动代替了您提到的内容或在您提到的内容之外。
马修(Matthew)

5

将先前检查的单选存储在变量中: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示例代码

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);

谢谢。我可能会把小提琴走得更远,然后存储收音机本身。这样,当值更改时,您可以引用以前选择的单选,而不仅仅是它的值。
马修

@Matthew实际上,我分享的小提琴只是存储radio元素,而不仅仅是存储值。记录该值以显示代码的用途,但未存储该值以备后用。我正在编辑变量名称,以使其更加清晰:previousChecked-> previousCheckedRadio,即-> currentCheckedRadio;
Dimitar Bonev

谢谢。这是一个很好的解决方案,除了使用跨浏览器无法正常运行的change事件。如果您使用click相反,那会更好。
马修(Matthew)

5

我意识到这是一个老问题,但是这段代码对我有用。也许将来某人会发现它有用:

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

1
如果添加,onkeydown="radioChange('juju','button1',radioArray);"您还可以捕获用户何时使用空间检查收音机。
马修

2

这只是我的脑袋,但是您可以为每个单选按钮执行一个onClick事件,为它们提供所有不同的ID,然后在事件中进行for循环以遍历组中的每个单选按钮,然后找出哪个是通过查看“已检查”属性进行了检查。选中的ID会存储为变量,但是您可能想先使用temp变量来确保该变量的值已更改,因为无论是否选中了新的单选按钮,click事件都会触发。


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>

2

如果要避免使用内联脚本,则只需在广播中收听click事件。这可以通过使用纯Javascript来实现,方法是监听以下事件的click事件:

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);
      }
}

2

您可以添加以下JS脚本

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

1

这对我有用

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

我认为这应该是答案,因为它已得到支持。
狮子座

0

这是最简单,最有效的功能,只需将要添加的任意数量的按钮添加到checked = false,并使每个单选按钮的onclick事件调用此功能。为每个单选按钮指定唯一编号

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

0

最简单,功能全面

使用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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.