Почему событие изменения jquery не срабатывает, когда я устанавливаю значение выбора с помощью val ()?

345

Логика в обработчике событий change() не запускается, когда значение установлено val(), но оно выполняется, когда пользователь выбирает значение с помощью мыши. Почему это?

<select id="single">
    <option>Single</option>
    <option>Single2</option>
</select>

<script>
    $(function() {
        $(":input#single").change(function() {
           /* Logic here does not execute when val() is used */
        });
    });

    $("#single").val("Single2");
</script>
Теги:
select
input

9 ответов

574
Лучший ответ

Поскольку для события change требуется фактическое событие браузера, инициированное пользователем, а не через код javascript.

Сделайте это вместо этого:

$("#single").val("Single2").trigger('change');

или

$("#single").val("Single2").change();
  • 1
    Привет, делаю это обновление выпадающего. но вызывается onChange () рекурсивно.
  • 3
    Я копаю этот ответ. Это работает, но разве нет лучшего способа с jQuery? Я уверен, что мы ВСЕ будем помнить делать это каждый раз, когда мы меняем значение, для которого настроен обработчик изменений (сарказм). Каркасы, которые используют привязку данных, могут решить эту проблему лучше?
Показать ещё 4 комментария
41

Я считаю, что вы можете вручную запустить событие изменения с помощью trigger():

$("#single").val("Single2").trigger('change');

Хотя это не срабатывает автоматически, я понятия не имею.

  • 0
    Я не могу заставить это работать, также $ ("# single"). Val ("Single2"). Change (); Я динамически создаю выпадающий список и меняю его значение (у меня это нормально работает) Но когда я пытаюсь вызвать изменения, у меня это не работает.
  • 4
    «Бит» запоздал, но он не срабатывает автоматически, потому что это приведет к бесконечным циклам. Подумайте, $('#foo').change(function() { $( this ).val( 'whatever' ); });
Показать ещё 2 комментария
8

Насколько я могу читать в API. Событие запускается только тогда, когда пользователь нажимает на параметр.

http://api.jquery.com/change/

Для выбора полей, флажков и радиокнопками, событие будет запущено сразу же, когда пользователь делает выбор с помощью мыши, но для другие типы элементов, событие откладывается до тех пор, пока элемент не теряет фокус.

  • 0
    Каковы альтернативы для других типов элементов? Я хочу, чтобы событие change срабатывало сразу для элементов input , а не когда элемент теряет фокус. Вы знаете?
  • 1
    Если под «немедленно» вы подразумеваете «всякий раз, когда нажимается клавиша на входе», вы ищете события onkeyup, onkeypress и onkeydown, а не onchange.
8

Добавление этой части кода после работы val():

$(":input#single").trigger('change');
  • 6
    Да, но вам не нужно делать отдельный выбор DOM для него с помощью $(":input#single") . На самом деле вы действительно не должны. Просто цепочка после .val() . Вы можете использовать .trigger('change') или .change() . Они точно такие же.
6

Чтобы упростить добавление пользовательской функции и вызвать ее, когда вы хотите, чтобы изменение значения также вызывало изменение

$.fn.valAndTrigger = function (element) {
    return $(this).val(element).trigger('change');
}

и

$("#sample").valAndTirgger("NewValue");

Или вы можете переопределить функцию val, чтобы всегда вызывать изменение при вызове val

(function ($) {
    var originalVal = $.fn.val;
    $.fn.val = function (value) {
        this.trigger("change");
        return originalVal.call(this, value);
    };
})(jQuery);

Образец в http://jsfiddle.net/r60bfkub/

  • 0
    Мой браузер жалуется на слишком много рекурсии, есть какое-то исправление для этого?
  • 0
    Вы прослушиваете событие- change элемента управления и выполняете обратный вызов, который (прямо или косвенно) снова запускает событие- change для того же элемента управления. Я предлагаю вам использовать другое название для события, вы вызываете вручную (например , explicit.change ), так что он не повторно курок change -Event, предотвращает петлю, и по- прежнему позволяет реагировать на события.
3

Если вы не хотите смешивать с событием изменения по умолчанию, вы можете предоставить свое собственное событие

$('input.test').on('value_changed', function(e){
    console.log('value changed to '+$(this).val());
});

чтобы инициировать событие по установленному значению, вы можете сделать

$('input.test').val('I am a new value').trigger('value_changed');
2

Я столкнулся с той же проблемой при использовании CMB2 с Wordpress и хотел подключиться к событию изменения файла uploadox exchange.

Поэтому, если вы не можете изменить код, вызывающий изменение (в данном случае CMB2 script), используйте код ниже. Триггер вызывается ПОСЛЕ того, как значение установлено, в противном случае ваше изменение eventHandler будет работать, но это будет предыдущий, а не тот, который установлен.

Здесь код, который я использую:

(function ($) {
    var originalVal = $.fn.val;
    $.fn.val = function (value) {
        if (arguments.length >= 1) {
            // setter invoked, do processing
            return originalVal.call(this, value).trigger('change');
        }
        //getter invoked do processing
        return originalVal.call(this);
    };
})(jQuery);
  • 0
    Это хорошо, но можете ли вы показать, как вы бы ограничили его только одним конкретным входом?
  • 0
    @jwebb Не совсем уверен, что ты имеешь в виду? Мы переопределяем функцию jQuery val (). Вы привязываете обработчик события изменения к определенному входу.
Показать ещё 1 комментарий
1
$(":input#single").trigger('change');

Это сработало для моего script. У меня есть 3 комбо и связать с событием chainSelect, мне нужно передать 3 значения по URL и по умолчанию выбрать все. Я использовал этот

$('#machineMake').val('<?php echo $_GET['headMake']; ?>').trigger('change');

И первое событие сработало.

  • 10
    Я надеюсь, вы никогда не делаете это в реальном мире. Само собой разумеется, что $ _GET [«что угодно»] нельзя доверять.
0

Если вы только что добавили опцию выбора в форму и хотите инициировать событие изменения, я обнаружил, что требуется setTimeout, иначе jQuery не заберет новый добавленный флажок:

window.setTimeout(function() { jQuery('.languagedisplay').change();}, 1);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню