Обробник подій OnChange для перемикача (тип INPUT = "радіо") не працює як одне значення


190

Я шукаю для цього узагальнене рішення.

Розглянемо 2 радіотехнічні входи з такою ж назвою. Після надсилання те, що перевіряється, визначає значення, яке надсилається за допомогою форми:

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

Подія зміни не спрацьовує, якщо вибрано перемикач. Отже, якщо радіо зі значенням = "1" вже вибрано, а користувач вибирає друге, handleChange1 () не запускається. Це створює проблему (для мене в будь-якому випадку) у тому, що немає жодної події, де я міг би впіймати цей відбір.

Мені б хотілося вирішити події onchange для значення групи прапорець або, як альтернатива, подія перевірки, яка виявляє не лише коли перевіряється радіо, але і коли воно не встановлено.

Я впевнений, що хтось із вас раніше стикався з цією проблемою. Які існують певні шляхи вирішення (або в ідеалі, що це правильний спосіб впоратися)? Я просто хочу спіймати подію зміни, отримати доступ до раніше перевіреного радіо, а також щойно перевіреного радіо.

PS
onclick здається кращою (крос-браузерною) подією, щоб вказати, коли радіо перевіряється, але це все ще не вирішує неперевірену проблему.

Я припускаю, що має сенс, чому onchange для типу прапорець працює у подібному випадку, оскільки він змінює значення, яке воно подає, коли ви перевіряєте чи скасовуєте його. Я хочу, щоб кнопки радіо поводилися більше як зміна елемента SELECT, але що ви можете зробити ...

Відповіді:


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
Лише зауваження про те, чому я вибрав це як правильну відповідь: Обробники подій клацання налаштовуються на кожну з перемикачів перемикача з атрибутом імені, myRadiosщоб прочитати змінну, prevяка містить вибране в даний час радіо. Здійснюється порівняння в кожному обробнику кліків, щоб визначити, чи радіо, яке натиснули, таке саме, як у збереженому, prevа якщо ні, то в ньому зберігається радіо, яке в даний момент натиснуто. У межах обробника клацань ви маєте доступ до обраного раніше: prevта поточно вибраного радіо:this
Метью

26
Було б краще кешувати функцію поза циклом, щоб усі радіостанції мали один і той же обробник подій (зараз вони мають однакові обробники, але вони різні функції). А може, покладіть всі радіостанції всередину обгортки та використовуйте делегацію подій
Оріол

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". Я насправді знав це з самого початку, але хотів звернути увагу на той факт, що зміна не працює, як можна було очікувати, і я хотів би впоратися з цим краще.
Матвій

1
Ви використовуєте JavaScript, правда? То чому б просто не підтримувати змінну, яка зберігає останню відому вибрану радіо-кнопку? Якщо ви використовуєте один обробник, ви можете перевірити це збережене значення, перш ніж перезаписати його новим значенням. +1
jmort253

13
@Matthew: onclickОбробник названий погано - він обробляє події вибору перемикача, натискаючи чи торкаючись кнопку чи активуючи кнопку натисканням клавіші "ввести" на клавіатурі. У onchangeцьому випадку обробник не є підходящим, оскільки значення вводу не змінюється, а лише атрибут, що перевіряється / не перевіряється. Я додав приклад сценарію для вирішення попереднього значення.
Нейт Кук

1
"onClick" не обробляє подію, якщо користувач використовував клавіатуру (вкладка + пробіл) для вибору радіо (і це звичайна практика у великих формах).
HoldOffHunger

+1. "onChange ()" - це не подія, що підлягає справі в ReactJS, і це єдине рішення. Джерело: github.com/facebook/react/isissue/1471
HoldOffHunger

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

і вибір, clickі changeподії запускаються під час вибору опції перемикання (принаймні в деяких браузерах).

Я також повинен зазначити, що в моєму прикладі clickподія все ще запускається, коли ви використовуєте вкладку та клавіатуру для вибору параметра.

Отже, моя думка полягає в тому, що незважаючи на те, що changeподія запускається в деяких браузерах, clickподія повинна забезпечити необхідне покриття.


6
Так, оскільки console.logв моєму коді є твердження, яке IE7 не підтримує. Ви можете просто попередити це в IE, якщо хочете.
Філіп Уолтон

Дякую. Це не стосується того, як отримати раніше вибраний прапорець. Також дякую, я не знав, що console.log не працює в IE.
Матвій

Не подвоюйте обробників подій - у веб-переглядачах, які запускають clickі changeобробники подій, і обробку подій, ви в кінцевому підсумку дзвоните оброблювачу двічі. У цьому випадку, оскільки @Matthew переймається попереднім значенням, це може призвести до поганих наслідків.
Нейт Кук

3
@NateCook ви явно пропустили пункт мого прикладу. Я показував, що щоразу, коли подія зміни запускається, подія натискання також знімається. Просто те, що я використовував обидва події у своєму прикладі, не означає, що я рекламував це. Я думаю, що ваш голосування було незаслужено.
Філіп Уолтон

Але ви рекламували це - ваша первісна відповідь сказала: "Отже, моя думка полягає в тому, що, навіть якщо подія зміни запускається в деяких браузерах, подія натискання повинна забезпечити необхідне покриття як резервне копіювання, і ви можете використовувати зміни в браузерах. які це підтримують ". click- це правильний обробник тут і єдиний, який вам потрібен. Ваша редакція пояснює це, тому я знімаю свій голос.
Нейт Кук

10

Що з використанням події зміни 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/


$(this).val()можна також замінити нативним javascript e.currentTarget.value, де e - об'єкт події, що передається через функцію зворотного виклику.
Ерік

6

Як ви бачите тут: http://www.w3schools.com/jsref/event_onchange.asp Атрибут onchange не підтримується для перемикачів.

Перше запитання, пов'язане вами, дає відповідь: onclickЗамість цього використовуйте подію та перевірте стан перемикача всередині функції, яка вона запускається.


Це просто трохи неповно. Отже, створивши функцію для обробки всіх кліків у групі, як би ви перевірили, чи не було вибрано вибране? Також я шукаю рішення, яке не потребує запитів.
Матвій

Клацнув перемикач буде встановлено прапорець, всі інші групи тієї ж групи будуть зняті. Або можна переглядати всі радіо кнопки цієї групи та перевіряти їх стан. Якщо ви надали більше інформації про те, що ви хочете робити за допомогою перемикачів, було б простіше сказати, як рухатись далі.
Константин Грос

2
onclickне є такою ж семантичною, тому що ви можете змінити перевіреність перемикача через введення клавіатури, якщо вибрано вибір форми клавіатури.
gsnedders

@gsnedders onclick, здається, працює за допомогою клавіатури в більшості браузерів - Firefox, IE, Safari, Chrome. Дивно, що він робить те, що має відбуватися зміна, але це робить. Мені цікаво, як це працює на мобільних платформах.
Матвій

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 був для мене недоступним, я знайшов би іншу роботу.
Адріан Карр

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 для перевірки, перш ніж відбувся натискання, але це не спрацює, коли ви використовуєте простір для вибору радіо. Може бути фокус події замість того, що ви згадали.
Матвій

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 Насправді загадка, якою я поділилася, зберігала радіоелемент, а не лише значення. Значення було записано для відображення мети коду, але воно не зберігалося для подальшого використання. Я редагую імена змінних, щоб стати більш уточненими: previousChecked -> previousCheckedRadio, що -> currentCheckedRadio;
Димитър Бонев

Дякую. Це хороше рішення, за винятком використання події зміни, яка не веде себе належним чином у крос-браузері. Якщо ви скористалися натисканням, то було б краще.
Матвій

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 для кожного перемикача, дати їм всі різні ідентифікатори, а потім зробити цикл for у випадку, щоб перейти через кожен перемикач у групі та знайти, який саме було перевірено, переглянувши атрибут "перевірений". Ідентифікований код, який перевіряється, буде зберігатися у вигляді змінної, але, можливо, спочатку потрібно використовувати змінну temp, щоб переконатися, що значення цієї змінної змінилося, оскільки подія клацання запустить, незалежно від того, чи була перевірена нова радіо-кнопка.


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

Якщо ви хочете уникати вбудованого сценарію, ви можете просто прослухати події по клацанню по радіо. Цього можна досягти за допомогою простого Javascript, прослухавши подію натискання на

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

Це найпростіша та найефективніша функція, яка використовується лише додаванням стільки кнопок, скільки ви хочете, щоб відмітити = 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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.