val () не вызывает change () в jQuery

343

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

Если вы наберете что-то в текстовых полях и нажмете где-нибудь еще, changeсрабатывает. Однако, если вы нажмете кнопку, значение текстового поля изменится, но changeне сработает. Зачем?

Ergec
источник
Заголовок сам ответил на мой вопрос. Подтверждено в .change () yellow «Примечание. Изменение значения элемента ввода с помощью JavaScript, например, с помощью .val (), не вызовет событие».
Боб Стейн
Жаль, что я столкнулся с stackoverflow.com/questions/11873721/… раньше, надеюсь, это поможет некоторым.
JeopardyTempest

Ответы:

454

onchange срабатывает только тогда, когда пользователь вводит данные, а затем ввод теряет фокус.

Вы можете вручную вызвать onchangeсобытие, используя после установки значения:

$("#mytext").change(); // someObject.onchange(); in standard JS

Кроме того, вы можете вызвать событие, используя:

$("#mytext").trigger("change");
djdd87
источник
18
не стесняйтесь расширять jquery и добавлять функцию say valWithChange, которая будет делать то, что вы хотите. Это не может быть действием по умолчанию, так как много раз вы не хотите, чтобы событие инициировалось автоматическим изменением значения, только когда пользователь взаимодействует с элементом
redsquare
8
Я хотел бы, чтобы этот ответ был отредактирован, чтобы рассмотреть возможность сцепления .change()с .val()методом.
Снексе
19
Причина может быть в том , что некоторые люди называют .val()в .change()потому , что они делают входную проверку. Срабатывание .change()на .val()вызовет бесконечный цикл.
yingted
7
Только если бы они меняли значение на что-то, что не прошло бы их собственную проверку, что было бы глупо.
Ленг
3
Я закончил тем, что привязался к blurвыполнению чего-то подобного:$('#mytext').focus().val('New text').blur();
Уэс Джонсон
63

Из превосходного предложения redsquare, это работает хорошо:

$.fn.changeVal = function (v) {
    return this.val(v).trigger("change");
}

$("#my-input").changeVal("Tyrannosaurus Rex");
Крис Фулстоу
источник
5
Вам не нужно оборачивать this:return this.val(v).trigger("change");
Мистер Поливирл
27

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

просто добавьте этот код где-нибудь в вашем документе (после загрузки jQuery)

(function($){
    var originalVal = $.fn.val;
    $.fn.val = function(){
        var result =originalVal.apply(this,arguments);
        if(arguments.length>0)
            $(this).change(); // OR with custom event $(this).trigger('value-changed');
        return result;
    };
})(jQuery);

Рабочий пример: здесь

(Обратите внимание, что это всегда будет срабатывать changeпри val(new_val)вызове, даже если значение на самом деле не изменилось.)

Если вы хотите инициировать изменение ТОЛЬКО, когда значение действительно изменилось, используйте это:

//This will trigger "change" event when "val(new_val)" called 
//with value different than the current one
(function($){
    var originalVal = $.fn.val;
    $.fn.val = function(){
        var prev;
        if(arguments.length>0){
            prev = originalVal.apply(this,[]);
        }
        var result =originalVal.apply(this,arguments);
        if(arguments.length>0 && prev!=originalVal.apply(this,[]))
            $(this).change();  // OR with custom event $(this).trigger('value-changed')
        return result;
    };
})(jQuery);

Живой пример для этого: http://jsfiddle.net/5fSmx/1/

Ярон У.
источник
4
Хм, ненужная заправка уток, я думаю :-р. Может быть лучше, как прокомментировал redsquare , дать такой функции другое имя, чем .val().
Бинки
1
Если вы переименуете его, вы должны изменить существующий код - таким образом, ваш существующий код продолжит работать
Yaron U.
4
Но тогда весь код, который был написан с правильным определением .val(), внезапно начнет вызывать побочные эффекты :-p.
Бинки,
2
Это также приведет к неправильной работе плагинов, что может быть не так легко исправить
SoWhat
1
Чтобы избежать побочных эффектов, я изменил функцию val, как указано выше, но я запускаю другое событие («val»), которое позволяет мне сохранить существующий код, но легко обрабатывает его всякий раз, когда мне нужно: $ (... ) .он ( 'изменение вала', ...)
ула
22

Вам нужно связать метод следующим образом:

$('#input').val('test').change();
Тимоти Гонсалес
источник
1
<3 для цепочки!
Gusstavv Gil
14

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

$('#mytext').change();

или:

$('#mytext').trigger('change');
Дарин димитров
источник
8

Похоже, события не кипят. Попробуй это:

$("#mybutton").click(function(){
  var oldval=$("#mytext").val();
  $("#mytext").val('Changed by button');
  var newval=$("#mytext").val();
  if (newval != oldval) {
    $("#mytext").trigger('change');
  }
});

Надеюсь, это поможет.

Я попробовал просто старое $("#mytext").trigger('change')без сохранения старого значения и .changeзапуска, даже если значение не изменилось. Поэтому я сохранил предыдущее значение и вызывал его $("#mytext").trigger('change')только в том случае, если оно изменилось.

Джей Годсе
источник
Удивило, что у этого не было больше голосов, так как это - текущая эффективная реализация изменения элемента HTML.
vol7ron
4

По состоянию на февраль 2019 года .addEventListener()в настоящее время не работает с jQuery .trigger()или .change(), вы можете проверить его ниже, используя Chrome или Firefox.

txt.addEventListener('input', function() {
  console.log('not called?');
})
$('#txt').val('test').trigger('input');
$('#txt').trigger('input');
$('#txt').change();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="txt">

Вы должны использовать .dispatchEvent()вместо этого.

txt.addEventListener('input', function() {
  console.log('it works!');
})
$('#txt').val('yes')
txt.dispatchEvent(new Event('input'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<input type="text" id="txt">

cieunteung
источник
1

С https://api.jquery.com/change/ :

changeСобытие посылается к элементу , когда изменяется его значение. Это событие ограничено <input>элементами, <textarea>ящиками и <select>элементами. Для полей выбора, флажков и переключателей событие вызывается немедленно, когда пользователь делает выбор с помощью мыши, но для других типов элементов событие откладывается до тех пор, пока элемент не потеряет фокус.

Sky Yip
источник
1

Я знаю, что это старая ветка, но для тех, кто ищет, вышеприведенные решения, возможно, не так хороши, как следующие, вместо проверки changeсобытий, проверки inputсобытий.

$("#myInput").on("input", function() {
    // Print entered value in a div box
    $("#result").text($(this).val());
});
Slipoch
источник