Tại sao sự kiện thay đổi jquery không kích hoạt khi tôi đặt giá trị của lựa chọn bằng val ()?


377

Logic trong change()trình xử lý sự kiện không được chạy khi giá trị được đặt theo val(), nhưng nó chạy khi người dùng chọn một giá trị bằng chuột. Tại sao lại thế này?

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

Câu trả lời:


589

Bởi vì changesự kiện này yêu cầu một sự kiện trình duyệt thực tế do người dùng khởi xướng thay vì thông qua mã javascript.

Thay vào đó, hãy làm điều này:

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

hoặc là

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

1
Xin chào, làm bản cập nhật này thả xuống. nhưng được gọi đệ quy onChange ().
Pankaj

3
Tôi đào câu trả lời này. Nó hoạt động, nhưng không có cách nào tốt hơn với jQuery? Tôi chắc chắn rằng tất cả chúng ta sẽ nhớ làm điều này mỗi khi chúng ta thay đổi một giá trị có trình xử lý thay đổi được thiết lập (mỉa mai). Các khung sử dụng ràng buộc dữ liệu có thể giải quyết điều này tốt hơn?
Jess

@ user113716 bạn có biết làm thế nào để kích hoạt nó mà không biết bất kỳ giá trị nào không?
BKSpurgeon

4
Tôi đồng ý đây là câu trả lời đúng nhưng điều này hoàn toàn hút và làm hỏng những gì tôi đang cố gắng làm.
Dustin Poissant

Hãy thử $ ("# đơn"). Kích hoạt ({loại: "thay đổi", val: "Đơn2"})
user2901633

44

Tôi tin rằng bạn có thể tự kích hoạt sự kiện thay đổi bằng trigger():

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

Mặc dù tại sao nó không tự động bắn, tôi không biết.


Tôi không thể làm việc này, cũng là $ ("# single"). Val ("Single2"). Change (); Tôi đang tự động tạo ra thả xuống và thay đổi giá trị của nó (Nó hoạt động tốt với tôi) Nhưng khi tôi đang cố gắng kích hoạt thay đổi thì nó không hoạt động với tôi.
Maneesh Kumar

4
Một "bit" muộn màng nhưng nó không tự động bắn vì nó sẽ dẫn đến các vòng lặp vô hạn. Hãy suy nghĩ$('#foo').change(function() { $( this ).val( 'whatever' ); });
JJJ

@Juhana Tôi nghĩ rằng một vòng lặp vô hạn dễ nhận thấy, chẩn đoán và sửa chữa hơn nhiều so với val () không thực sự kích hoạt các ràng buộc "thay đổi".
iono

Gọi .change () là cách viết tắt để gọi .trigger ('thay đổi').
Triynko

9

Thêm đoạn mã này sau khi val () dường như hoạt động:

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

6
Có, nhưng bạn không cần phải thực hiện lựa chọn DOM riêng cho nó $(":input#single"). Trong thực tế, bạn thực sự không nên. Chỉ cần chuỗi nó sau .val(). Bạn có thể sử dụng .trigger('change')hoặc .change(). Họ là chính xác như nhau.
dùng113716

8

Theo như tôi có thể đọc trong API. Sự kiện chỉ được kích hoạt khi người dùng nhấp vào một tùy chọn.

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

Đối với các hộp chọn, hộp kiểm và nút radio, sự kiện sẽ được kích hoạt ngay lập tức khi người dùng thực hiện lựa chọn bằng chuột, nhưng đối với các loại phần tử khác, sự kiện được hoãn lại cho đến khi phần tử mất tiêu điểm.


Các lựa chọn thay thế cho các loại yếu tố khác là gì? Tôi muốn sự kiện 'thay đổi' kích hoạt ngay lập tức cho inputcác phần tử, không phải khi phần tử mất tiêu điểm. Bạn có biết?
Dan Nissenbaum

1
Nếu bằng "ngay lập tức", bạn có nghĩa là "bất cứ khi nào một phím được nhấn trong đầu vào" bạn đang tìm kiếm các sự kiện onkeyup, onkeypress và onkeydown, không phải trao đổi.
dùng2867288

6

Để dễ dàng hơn, hãy thêm chức năng tùy chỉnh và gọi nó khi bạn muốn thay đổi giá trị cũng kích hoạt thay đổi

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

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

Hoặc bạn có thể ghi đè hàm val để luôn gọi thay đổi khi val được gọi

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

Mẫu tại http://jsfiddle.net/r60bfkub/


Trình duyệt của tôi phàn nàn về quá nhiều đệ quy, bất kỳ sửa chữa cho điều này?
Bhargav Nanekalva

Bạn đang lắng nghe sự changeliên quan đến một điều khiển và thực hiện một cuộc gọi lại mà (trực tiếp hoặc gián tiếp) kích hoạt lại lần nữa changeđối với cùng một điều khiển. Tôi khuyên bạn nên sử dụng tên khác cho sự kiện mà bạn kích hoạt bằng tay (ví dụ explicit.change), để nó không kích hoạt lại change-event, ngăn chặn vòng lặp và vẫn cho phép bạn phản ứng với sự kiện.
Kamafeather

3

Trong trường hợp bạn không muốn kết hợp với sự kiện thay đổi mặc định, bạn có thể cung cấp sự kiện tùy chỉnh của mình

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

để kích hoạt sự kiện trên tập giá trị, bạn có thể làm

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

3

Tôi gặp vấn đề tương tự khi sử dụng CMB2 với Wordpress và muốn tham gia vào sự kiện thay đổi của metabox tải lên tệp.

Vì vậy, trong trường hợp bạn không thể sửa đổi mã gọi thay đổi (trong trường hợp này là tập lệnh CMB2), hãy sử dụng mã bên dưới. Trình kích hoạt đang được gọi SAU giá trị được đặt, nếu không, sự kiện thay đổi của bạn sẽ hoạt động, nhưng giá trị sẽ là giá trị trước đó, không phải giá trị được đặt.

Đây là mã tôi sử dụng:

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

Điều này là tốt, nhưng bạn có thể chỉ ra cách bạn sẽ giới hạn nó chỉ trong một đầu vào cụ thể không?
jwebb

@jwebb Không chắc lắm ý bạn là gì? Chúng ta đang ghi đè hàm jQuery val (). Bạn liên kết một trình xử lý sự kiện thay đổi với một đầu vào cụ thể.
dùng2075039

Ý tôi là, @ user2075039, nếu có nhiều đầu vào trên trang sử dụng hàm jQuery val () và bạn không muốn liên kết trình xử lý sự kiện thay đổi tùy chỉnh với TẤT CẢ chúng mà chỉ là một trong số chúng?
jwebb

@jwebb bạn có thể kiểm tra this.selectorbên trong $.fn.valchức năng ghi đè , cho một bộ chọn cụ thể (sẽ phụ thuộc vào những gì được sử dụng cho bộ chọn). Đây là điều tốt nhất tôi đã tìm thấy để làm điều này chỉ cho các trường cụ thể, vấn đề duy nhất là bạn phải biết những gì họ đang sử dụng cho bộ chọn
sMstyle

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

Điều này làm việc cho kịch bản của tôi. Tôi có 3 combo và liên kết với sự kiện chainSelect, tôi cần chuyển 3 giá trị theo url & mặc định chọn tất cả thả xuống. Tôi đã sử dụng cái này

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

Và sự kiện đầu tiên đã làm việc.


10
Tôi hy vọng, bạn không bao giờ làm điều này trong thế giới thực. Không cần phải nói rằng $ _GET ['anything'] không thể tin cậy được.
Denis V

1

Nếu bạn vừa thêm tùy chọn chọn vào một biểu mẫu và bạn muốn kích hoạt sự kiện thay đổi, tôi đã tìm thấy một setTimeout là bắt buộc nếu không jQuery không chọn hộp chọn mới được thêm vào:

window.setTimeout(function() { jQuery('.languagedisplay').change();}, 1);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.