为什么使用val()设置select的值时,jquery更改事件不会触发?


当value val()val()设置时, change()事件处理程序中的逻辑没有运行,但是当用户用鼠标选择一个值时,它会运行。 为什么是这样?

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


Answers



因为change事件需要由用户启动的实际浏览器事件,而不是通过JavaScript代码。

做这个,而不是:

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



我相信你可以用trigger()手动触发change事件:

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

虽然为什么不自动启动,我不知道。




据我可以在API的阅读。 只有当用户点击一个选项时才会触发事件。

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

对于选择框,复选框和单选按钮,当用户使用鼠标进行选择时会立即触发事件,而对于其他元素类型,事件将被推迟,直到元素失去焦点。




在val()之后添加这段代码似乎工作:

$(":input#single").trigger('change');



为了使它更容易添加一个自定义函数,并调用它,当你想改变的值也触发改变

$.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/的示例




如果您不想与默认更改事件混淆,则可以提供自定义事件

$('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');



$(":input#single").trigger('change');

这适用于我的脚本。 我有3个组合和绑定与chainSelect事件,我需要传递3个值的网址和默认选择所有下拉菜单。 我用这个

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

而第一个事件的工作。




我遇到同样的问题,同时使用Wordpress的CMB2,并想挂钩文件上传元框的更改事件。

因此,如果您无法修改调用更改的代码(在本例中为CMB2脚本),请使用下面的代码。 触发器被调用后,值设置,否则你的变化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);



如果你刚刚添加选择选项到一个表单,并希望触发更改事件,我发现一个setTimeout是必需的,否则jQuery不拿起新添加的选择框:

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