Trình xử lý sự kiện OnChange cho nút radio (loại INPUT = radio radio) không hoạt động như một giá trị


190

Tôi đang tìm kiếm một giải pháp tổng quát cho việc này.

Hãy xem xét 2 đầu vào loại radio có cùng tên. Khi được gửi, giá trị được kiểm tra sẽ xác định giá trị được gửi với biểu mẫu:

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

Sự kiện thay đổi không kích hoạt khi bỏ nút radio. Vì vậy, nếu radio có value = "1" đã được chọn và người dùng chọn thứ hai, handleChange1 () sẽ không chạy. Điều này trình bày một vấn đề (đối với tôi dù thế nào) ở chỗ không có sự kiện nào tôi có thể nắm bắt được lựa chọn này.

Những gì tôi muốn là một cách giải quyết cho sự kiện onchange cho giá trị nhóm hộp kiểm hoặc thay vào đó là một sự kiện oncheck phát hiện không chỉ khi radio được kiểm tra mà cả khi nó không được chọn.

Tôi chắc rằng một số bạn đã gặp phải vấn đề này trước đây. Một số cách giải quyết (hoặc lý tưởng nhất là cách đúng đắn để xử lý việc này) là gì? Tôi chỉ muốn nắm bắt sự kiện thay đổi, truy cập vào đài phát thanh đã kiểm tra trước đó cũng như đài phát thanh mới được kiểm tra.

PS
onclick có vẻ như là một sự kiện tốt hơn (trình duyệt chéo) để cho biết khi nào radio được kiểm tra nhưng nó vẫn không giải quyết được vấn đề chưa được kiểm tra.

Tôi cho rằng nó có ý nghĩa tại sao onchange cho một loại hộp kiểm hoạt động trong trường hợp như thế này vì nó thay đổi giá trị mà nó gửi khi bạn kiểm tra hoặc bỏ chọn nó. Tôi ước các nút radio hoạt động giống như trao đổi của phần tử CHỌN nhưng bạn có thể làm gì ...

Câu trả lời:


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>

Đây là bản demo của JSFiddle: https://jsfiddle.net/crp6em1z/


4
Chỉ cần một lưu ý về lý do tại sao tôi chọn đây là câu trả lời đúng: Trình xử lý sự kiện nhấp được thiết lập trên mỗi nút radio với thuộc tính tên myRadiosđể đọc biến prevgiữ radio hiện được chọn. Một so sánh được thực hiện trong mỗi trình xử lý nhấp để quyết định xem radio đã nhấp có giống với radio được lưu trong không prevvà nếu không thì radio được nhấp hiện tại có được lưu ở đó không. Trong trình xử lý nhấp chuột, bạn có quyền truy cập vào đài đã chọn trước đó prevvà radio hiện được chọn:this
Matthew

26
Sẽ tốt hơn nếu lưu trữ chức năng bên ngoài vòng lặp, để tất cả các bộ đàm chia sẻ cùng một trình xử lý sự kiện (bây giờ chúng có các trình xử lý giống hệt nhau nhưng chúng là các chức năng khác nhau). Hoặc có thể đặt tất cả các bộ đàm bên trong một vỏ bọc và sử dụng phái đoàn sự kiện
Oriol

1
@Oriol, hoặc bất cứ ai có kiến ​​thức, bạn có thể đưa ra một ví dụ về (1) bộ nhớ đệm bên ngoài vòng lặp hoặc (2) trình bao bọc + ủy nhiệm sự kiện?
Matt Voda


14
onclick không hoạt động với lựa chọn bàn phím, bạn có thể sử dụng rad[i].addEventListener('change', function(){ //your handler code })và nó sẽ hoạt động cho cả chuột và bàn phím
Juanmi Rodriguez

117

Tôi sẽ thực hiện hai thay đổi:

<input type="radio" name="myRadios" onclick="handleClick(this);" value="1" />
<input type="radio" name="myRadios" onclick="handleClick(this);" value="2" />
  1. Sử dụng onclicktrình xử lý thay vì onchange- bạn đang thay đổi "trạng thái đã kiểm tra" của đầu vào radio, chứ không phải value, vì vậy không có sự kiện thay đổi nào xảy ra.
  2. Sử dụng một hàm duy nhất và truyền thisdưới dạng tham số, điều này sẽ giúp bạn dễ dàng kiểm tra giá trị nào hiện đang được chọn.

ETA: Cùng với handleClick()chức năng của bạn , bạn có thể theo dõi giá trị gốc / cũ của radio trong một biến có phạm vi trang. Đó là:

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


Cảm ơn, mặc dù điều này không giải quyết được vấn đề phải có đài phát thanh đã kiểm tra trước đó và bạn cũng nói rõ một điều mà người dùng khác đã đề cập đó là sử dụng "onclick" thay vì "onchange". Tôi thực sự đã biết điều này ngay từ đầu nhưng tôi muốn thu hút sự chú ý đến thực tế là onchange không hoạt động như người ta mong đợi và tôi muốn xử lý nó tốt hơn.
Matthew

1
Bạn đang sử dụng JavaScript, phải không? Vậy tại sao không chỉ duy trì một biến lưu trữ nút radio được chọn cuối cùng? Nếu bạn đang sử dụng một trình xử lý duy nhất, thì bạn có thể kiểm tra giá trị được lưu trữ này trước khi bạn ghi đè lên nó bằng giá trị mới. +1
jmort253

13
@Matthew: Trình onclickxử lý chỉ được đặt tên kém - nó xử lý sự kiện chọn nút radio cho dù nút đó được nhấp, chạm hoặc kích hoạt bằng cách nhấn "enter" trên bàn phím. Trình onchangexử lý không phù hợp trong trường hợp này vì giá trị của đầu vào không thay đổi, chỉ có thuộc tính được kiểm tra / không được kiểm tra. Tôi đã thêm một tập lệnh ví dụ để giải quyết giá trị trước đó.
Nate Cook

1
"onClick" sẽ không xử lý sự kiện nếu người dùng sử dụng bàn phím (tab + phím cách) để chọn radio (và đây là cách phổ biến trên các hình thức lớn).
Hold OfferHunger

+1. "onChange ()" không phải là một sự kiện có thể xảy ra trong ReactJS và đây là giải pháp duy nhất. Nguồn: github.com/facebook/react/issues/1471
Hold OfferHunger

42

Như bạn có thể thấy từ ví dụ này: 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);
});

cả sự kiện clickchangesự kiện đều được kích hoạt khi chọn tùy chọn nút radio (ít nhất là trong một số trình duyệt).

Tôi cũng nên chỉ ra rằng trong ví dụ của tôi, clicksự kiện vẫn được kích hoạt khi bạn sử dụng tab và bàn phím để chọn một tùy chọn.

Vì vậy, quan điểm của tôi là mặc dù changesự kiện được kích hoạt là một số trình duyệt, clicksự kiện sẽ cung cấp phạm vi bảo hiểm bạn cần.


6
Có, bởi vì có một console.logtuyên bố trong mã của tôi, mà IE7 không hỗ trợ. Bạn chỉ có thể cảnh báo nó trong IE nếu bạn muốn.
Philip Walton

Cảm ơn. Điều này không giải quyết làm thế nào để có được hộp kiểm đã chọn trước đó. Cũng cảm ơn, tôi không biết console.log không hoạt động trong IE.
Matthew

Đừng nhân đôi các trình xử lý sự kiện - trong các trình duyệt kích hoạt cả trình xử lý sự kiện clickchangetrình xử lý sự kiện, cuối cùng bạn sẽ gọi trình xử lý hai lần. Trong trường hợp này, vì @Matthew quan tâm đến giá trị trước đó, điều đó có thể dẫn đến hậu quả xấu.
Nate Cook

3
@NateCook bạn rõ ràng đã bỏ lỡ điểm của ví dụ của tôi. Tôi đã cho thấy rằng bất cứ khi nào sự kiện thay đổi được kích hoạt, sự kiện nhấp cũng được kích hoạt. Chỉ vì tôi đã sử dụng cả hai sự kiện trong ví dụ của mình không có nghĩa là tôi đang quảng bá nó. Tôi nghĩ rằng phiếu bầu của bạn là không xứng đáng.
Philip Walton

Nhưng bạn đã quảng cáo nó - câu trả lời ban đầu của bạn cho biết "Vì vậy, quan điểm của tôi là mặc dù sự kiện thay đổi được kích hoạt là một số trình duyệt, sự kiện nhấp sẽ cung cấp phạm vi bảo hiểm bạn cần như một dự phòng và bạn có thể sử dụng thay đổi trong trình duyệt hỗ trợ nó. " clicklà xử lý chính xác ở đây và là người duy nhất bạn cần. Bản sửa đổi của bạn làm rõ điều đó, vì vậy tôi sẽ bỏ phiếu bầu của tôi xuống.
Nate Cook

10

Còn việc sử dụng sự kiện thay đổi của Jquery thì sao?

$(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()cũng có thể được thay thế bằng javascript gốc e.currentTarget.value, trong đó e là đối tượng sự kiện được truyền qua chức năng gọi lại.
Eric

6

Như bạn có thể thấy ở đây: http://www.w3schools.com/jsref/event_onchange.asp Thuộc tính onchange không được hỗ trợ cho các nút radio.

Câu hỏi SO đầu tiên được liên kết bởi bạn cung cấp cho bạn câu trả lời: onclickThay vào đó hãy sử dụng sự kiện và kiểm tra trạng thái nút radio bên trong chức năng mà nó kích hoạt.


Đây chỉ là một chút không đầy đủ. Vì vậy, sau khi tạo một hàm để xử lý tất cả các nhấp chuột trong nhóm, bạn sẽ kiểm tra xem cái nào đã được bỏ chọn? Ngoài ra, tôi đang tìm kiếm một giải pháp không jquery.
Matthew

Nút radio đã nhấp sẽ được kiểm tra, tất cả những người khác trong cùng nhóm sẽ không được chọn. Hoặc, bạn có thể lặp qua tất cả các nút radio của nhóm đó và kiểm tra trạng thái của chúng. Nếu bạn cung cấp thêm thông tin về những gì bạn muốn làm với các nút radio, việc cho bạn biết cách tiếp tục sẽ dễ dàng hơn.
Constantin Groß

2
onclickkhông phải là cùng một ngữ nghĩa, vì bạn có thể thay đổi độ kiểm tra của nút radio thông qua đầu vào bàn phím cho phép lựa chọn hình thức bàn phím được bật.
gsnedder

@ssnedder onclick dường như hoạt động thông qua đầu vào bàn phím trong hầu hết các trình duyệt - Firefox, IE, Safari, Chrome. Thật kỳ lạ khi nó thực hiện những gì onchange phải làm, nhưng nó làm. Tôi tò mò làm thế nào điều này hoạt động trên nền tảng di động mặc dù.
Matthew

1
w3schools cho 1 và không giải quyết được toàn bộ vấn đề cho 2, đó là cách lấy radio đã chọn trước đó. 2 là phần quan trọng nhất của câu hỏi trong tâm trí của tôi.
Matthew

6

Tôi không nghĩ có cách nào khác để lưu trữ trạng thái trước đó. Đây là giải pháp với 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" />

Sau khi suy nghĩ về nó nhiều hơn một chút, tôi quyết định loại bỏ biến và thêm / xóa lớp. Đây là những gì tôi nhận được: http://jsfiddle.net/BeQh3/2/


1
Tôi đã nghĩ về việc sử dụng một jQuery và chắc chắn còn rất nhiều điều có thể được thực hiện với nó. Bạn có thể liên kết một số sự kiện tùy chỉnh để kiểm tra và bỏ chọn và thậm chí kiểm tra các yêu cầu của trình duyệt chéo. Âm thanh như một ý tưởng tốt cho một plugin.
Matthew

Cảm ơn. Tôi thích jQuery nhưng nó không có sẵn cho tôi trong trường hợp này.
Matthew

JQuery không có sẵn cho bạn như thế nào?
jmort253

1
Nếu jQuery không có sẵn cho tôi, tôi sẽ tìm một công việc khác.
Adrian Carr

5

Có, không có sự kiện thay đổi cho nút radio hiện được chọn. Nhưng vấn đề là khi mỗi nút radio được lấy làm một yếu tố riêng biệt. Thay vào đó, một nhóm phát thanh nên được coi là một yếu tố duy nhất như thế nào select. Vì vậy, sự kiện thay đổi được kích hoạt cho nhóm đó. Nếu đó là một selectyếu tố chúng ta không bao giờ lo lắng về từng tùy chọn trong đó, mà chỉ lấy tùy chọn đã chọn. Chúng tôi lưu trữ giá trị hiện tại trong một biến sẽ trở thành giá trị trước đó, khi một tùy chọn mới được chọn. Tương tự, bạn phải sử dụng một biến riêng để lưu giá trị của nút radio đã kiểm tra.

Nếu bạn muốn xác định nút radio trước đó, bạn phải lặp lại mousedownsự kiện.

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

xem cái này: http://jsfiddle.net/diode/tywx6/2/


Tôi đã nghĩ về việc sử dụng mousedown để kiểm tra trước khi nhấp chuột xảy ra nhưng điều đó sẽ không hiệu quả khi sử dụng không gian để chọn radio. Có thể sự kiện tập trung thay cho hoặc ngoài những gì bạn đã đề cập.
Matthew

5

Lưu trữ radio đã kiểm tra trước đó trong một biến:
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

Mã não

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

MÃ VÍ DỤ

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

Cảm ơn. Tôi có thể đưa câu đố xa hơn một chút và lưu trữ radio. Bằng cách này khi giá trị thay đổi, bạn có một tham chiếu đến radio đã chọn trước đó thay vì chỉ là giá trị của nó.
Matthew

@Matthew Trên thực tế, câu đố mà tôi chia sẻ là lưu trữ phần tử radio và không chỉ giá trị. Giá trị được ghi lại để hiển thị mục đích của mã nhưng nó không được lưu trữ để sử dụng sau này. Tôi đang chỉnh sửa tên biến để trở nên rõ ràng hơn: trướcChecked -> trướcCheckedRadio, rằng -> currentCheckedRadio;
Dimitar Bonev

Cảm ơn. Đây là một giải pháp tốt ngoại trừ việc sử dụng sự kiện thay đổi không hoạt động đúng trình duyệt chéo. Nếu bạn sử dụng bấm thay vào đó sẽ tốt hơn.
Matthew

5

Tôi nhận ra đây là một vấn đề cũ, nhưng đoạn mã này hoạt động với tôi. Có lẽ ai đó trong tương lai sẽ thấy nó hữu ích:

<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
Nếu bạn thêm, onkeydown="radioChange('juju','button1',radioArray);"bạn cũng có thể chụp khi người dùng sử dụng không gian để kiểm tra radio.
Matthew

2

Đây chỉ là trên đỉnh đầu của tôi, nhưng bạn có thể thực hiện một sự kiện onClick cho mỗi nút radio, cung cấp cho họ tất cả các ID khác nhau và sau đó tạo một vòng lặp for trong sự kiện để đi qua từng nút radio trong nhóm và tìm ra đó là đã được kiểm tra bằng cách xem thuộc tính 'đã kiểm tra'. Id của cái được kiểm tra sẽ được lưu dưới dạng một biến, nhưng trước tiên bạn có thể muốn sử dụng biến tạm thời để đảm bảo rằng giá trị của biến đó đã thay đổi, vì sự kiện nhấp sẽ kích hoạt dù có chọn nút radio mới hay không.


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

Nếu bạn muốn tránh tập lệnh nội tuyến, bạn chỉ cần nghe một sự kiện nhấp chuột trên radio. Điều này có thể đạt được với Javascript đơn giản bằng cách nghe một sự kiện nhấp chuột vào

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

Bạn có thể thêm tập lệnh JS sau

<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

cái này hiệu quả với tôi

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

Tôi nghĩ rằng đây sẽ là câu trả lời ngay bây giờ khi nó được hỗ trợ.
Leo

0

Đây là chức năng dễ dàng và hiệu quả nhất để sử dụng chỉ cần thêm bao nhiêu nút mà bạn muốn vào check = false và tạo sự kiện onclick của mỗi nút radio gọi chức năng này. Chỉ định một số duy nhất cho mỗi nút radio

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

0

Dễ nhất và đầy đủ sức mạnh

chỉ đọc các đầu vào radio bằng getAttribution

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.