Обработчик события OnChange для радиокнопки (INPUT type = «radio») не работает как одно значение


192

Я ищу обобщенное решение для этого.

Рассмотрим 2 входа типа радио с одинаковым именем. При отправке проверяется значение, которое отправляется с формой:

<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, но что вы можете сделать ...

Ответы:


180

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
Просто заметка о том, почему я выбрал это как правильный ответ: обработчики событий Click устанавливаются на каждой из радиокнопок с атрибутом name, myRadiosчтобы прочитать переменную, prevкоторая содержит текущую выбранную радиостанцию. Сравнение выполняется в каждом обработчике кликов, чтобы определить, совпадает ли радио, на которое нажали, с тем, которое хранится в, prevи если нет, то в нем хранится радио, на которое щелкают в данный момент. В обработчике кликов у вас есть доступ к ранее выбранному: prevи текущему выбранному радио:this
Матфея

26
Было бы лучше кэшировать функцию вне цикла, чтобы все радиоустройства совместно использовали один и тот же обработчик событий (теперь они имеют идентичные обработчики, но это разные функции). Или, может быть, положить все радио в оболочку и использовать делегирование событий
Oriol

1
@Oriol, или кто-нибудь знающий, не могли бы вы привести пример (1) кэширования вне цикла или (2) оболочки + делегирование события?
Мэтт Вода


14
Onclick не работает с выбором клавиатуры, вы можете использовать, rad[i].addEventListener('change', function(){ //your handler code })и он будет работать как для мыши, так и для клавиатуры
Хуанми Родригес

118

Я бы сделал два изменения:

<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Обработчик не подходит в данном случае , так как значение входного сигнала не меняется, только проверенным / непроверенной атрибут. Я добавил пример сценария для решения предыдущего значения.
Нейт Кук,

1
«onClick» не будет обрабатывать событие, если пользователь использовал клавиатуру (вкладка + пробел) для выбора радио (и это обычная практика для больших форм).
HoldOffHunger

+1. «onChange ()» не является событием с возможностью запуска в ReactJS, и это единственное решение. Источник: github.com/facebook/react/issues/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 вы явно не поняли смысл моего примера. Я показывал, что всякий раз, когда происходит событие изменения, также происходит событие щелчка. То, что я использовал оба события в своем примере, не означает, что я продвигал его. Я думаю, что ваш голос был незаслуженным.
Филипп Уолтон

Но вы продвигали его - ваш первоначальный ответ гласил: «Итак, я хочу сказать, что, хотя событие change запускается некоторыми браузерами, событие click должно предоставить необходимое покрытие в качестве запасного варианта, и вы можете использовать изменение в браузерах. которые поддерживают это. " 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 не поддерживается для переключателей.

Первый связанный с вами вопрос SO дает вам ответ: используйте onclickсобытие вместо этого и проверьте состояние переключателя внутри функции, которую оно вызывает.


Это немного неполноценно. Итак, после создания функции для обработки всех кликов в группе, как бы вы проверили, какой из них был отменен? Кроме того, я ищу решение не для jquery.
Матфея

Выбранный переключатель будет отмечен, все остальные в той же группе будут отключены. Или вы можете просмотреть все переключатели этой группы и проверить их статус. Если бы вы предоставили больше информации о том, что вы хотите делать с переключателями, было бы проще рассказать вам, как это сделать.
Константин Грос

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

@gsnedders onclick, кажется, работает через клавиатурный ввод в большинстве браузеров - Firefox, IE, Safari, Chrome. Странно, что он делает то, что должен делать onchange, но он делает. Мне интересно, как это работает на мобильных платформах.
Мэтью

1
w3schools for 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, that -> currentCheckedRadio;
Димитар Бонев

Спасибо. Это хорошее решение, за исключением использования события change, которое не работает должным образом в разных браузерах. Если бы вы использовали вместо этого клик, было бы лучше.
Мэтью

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 для каждой радиокнопки, присвоить им разные идентификаторы, а затем создать цикл для события, чтобы просмотреть каждую радиокнопку в группе и найти был проверен, посмотрев на атрибут «флажок». Идентификатор отмеченного будет сохранен как переменная, но вы можете сначала использовать временную переменную, чтобы убедиться, что значение этой переменной изменилось, так как событие 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

Если вы хотите избежать встроенного скрипта, вы можете просто прослушать событие клика по радио. Это может быть достигнуто с простым 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.