Nhận giá trị của lựa chọn (thả xuống) trước khi thay đổi


237

Điều tôi muốn đạt được là bất cứ khi nào <select>thay đổi thả xuống tôi muốn giá trị của danh sách thả xuống trước khi thay đổi. Tôi đang sử dụng phiên bản 1.3.2 của jQuery và sử dụng sự kiện thay đổi nhưng giá trị tôi nhận được là sau khi thay đổi.

<select name="test">
<option value="stack">Stack</option>
<option value="overflow">Overflow</option>
<option value="my">My</option>
<option value="question">Question</option>
</select>

Hãy nói rằng tùy chọn hiện tại My được chọn ngay bây giờ khi tôi thay đổi nó thành stack trong sự kiện onchange (tức là khi tôi thay đổi nó thành stack) Tôi muốn đó là giá trị trước đó tức là tôi mong đợi trong trường hợp này.

Làm thế nào điều này có thể đạt được?

Chỉnh sửa: Trong trường hợp của tôi, tôi có nhiều hộp chọn trong cùng một trang và muốn áp dụng điều tương tự cho tất cả chúng. Ngoài ra tất cả các lựa chọn của tôi được chèn sau khi tải trang thông qua ajax.


1
Bạn đã kiểm tra cái này chưa: stackoverflow.com/questions/1983535/
Kẻ

Câu trả lời:


434

Kết hợp sự kiện trọng tâm với sự kiện thay đổi để đạt được những gì bạn muốn:

(function () {
    var previous;

    $("select").on('focus', function () {
        // Store the current value on focus and on change
        previous = this.value;
    }).change(function() {
        // Do something with the previous value after the change
        alert(previous);

        // Make sure the previous value is updated
        previous = this.value;
    });
})();

Ví dụ hoạt động: http://jsfiddle.net/x5PKf/766


1
@Alpesh: Thật không may, vì bạn không sử dụng jQuery 1.4.1 trở lên, nên bạn không thể sử dụng live () với sự kiện tập trungthay đổi . Điều duy nhất bạn có thể làm là điều chỉnh tập lệnh của mình để liên kết sau khi các phần tử được chèn vào trang.
Andy E

1
Cảm ơn tôi đã gắn kết cả hai với trực tiếp và nó hoạt động thành công. :)
Alpesh

4
Lưu ý rằng bạn cũng nên tập trung vào phần tử được chọn trong trình xử lý thay đổi của mình, nếu không nó sẽ không được kích hoạt sau khi thay đổi giá trị lặp lại
Alex

52
Tôi không đồng ý với giải pháp này. Nếu bạn thay đổi giá trị một lần nó sẽ hoạt động nhưng nếu bạn làm điều đó một lần nữa thì nó sẽ không. Bạn phải nhấp vào một nơi nào đó để mất tập trung và một lần nhấp khác vào danh sách thả xuống. Tôi đề xuất: $ ("# dropdownId"). On ('thay đổi', function () {var ddl = $ (this); var trước = ddl.data ('trước'); ddl.data ('trước', ddl .val ());});
free4ride

5
@ free4ride, để sửa lỗi mà tôi chỉ cần gọi $(this).blur();vào cuối chức năng thay đổi
chiliNUT

135

vui lòng không sử dụng var toàn cầu cho việc này - lưu trữ giá trị trước tại dữ liệu ở đây là một ví dụ: http://jsbin.com/uqupu3/2/edit

mã cho ref:

$(document).ready(function(){
  var sel = $("#sel");
  sel.data("prev",sel.val());

  sel.change(function(data){
     var jqThis = $(this);
     alert(jqThis.data("prev"));
     jqThis.data("prev",jqThis.val());
  });
});

chỉ cần thấy rằng bạn có nhiều lựa chọn trên trang - phương pháp này cũng sẽ hiệu quả với bạn vì với mỗi lựa chọn, bạn sẽ lưu trữ giá trị trước trên dữ liệu của lựa chọn


jQuery.data là một giải pháp tốt ở đây. tại giải pháp của bạn, bạn đang tạo một bao đóng cho mỗi lựa chọn có tác động hoàn hảo nếu có nhiều yếu tố được chọn
Avi Pinto

Mối quan tâm của tôi không phải là về hiệu suất và tôi không tin rằng việc tạo các chức năng chậm hơn bất kỳ cách nào jQuery.data.
Tháng 8 Lilleaas

9
vậy sự phản đối của bạn khi sử dụng jQuery.data là gì? theo như tôi biết thì thư viện jQuery cũng sử dụng nó trong nội bộ và khuyên bạn nên sử dụng nó
Avi Pinto

Chắc chắn đồng ý với việc sử dụng Dữ liệu jQuery - cảm ơn vì đã nhắc nhở tôi Tôi sắp sử dụng var toàn cầu .. Không có gì sai với var toàn cầu nhưng sử dụng dữ liệu ngắn gọn hơn. Nhưng tập trung chuỗi và sau đó thay đổi cũng tốt đẹp :)
Piotr Kula

4
@ppumkin: Một điều chắc chắn sai với một biến toàn cục: Nó chỉ hỗ trợ một biến select! Câu trả lời được chấp nhận sẽ phá vỡ vì nó phù hợp với tất cả selectnhưng chỉ lưu trữ giá trị của câu đầu tiên. data cách tốt hơn để làm điều đó. +1 :)
Mã hóa đã qua

86

Tôi đi tìm giải pháp Avi Pinto sử dụng jquery.data()

Sử dụng tập trung không phải là một giải pháp hợp lệ. Nó hoạt động ở lần đầu tiên bạn thay đổi các tùy chọn, nhưng nếu bạn ở trên phần tử chọn đó và nhấn phím "lên" hoặc "xuống". Nó sẽ không đi qua sự kiện tập trung một lần nữa.

Vì vậy, giải pháp nên giống như sau,

//set the pre data, usually needed after you initialize the select element
$('mySelect').data('pre', $(this).val());

$('mySelect').change(function(e){
    var before_change = $(this).data('pre');//get the pre data
    //Do your work here
    $(this).data('pre', $(this).val());//update the pre data
})

3
Giải pháp tuyệt vời, tốt hơn nhiều so với câu trả lời được lựa chọn!
TJL

2
Phần thứ hai hoạt động tốt nhưng phần thứ nhất không thiết lập thuộc tính dữ liệu. Có ý kiến ​​gì không?
Sina

1
@ Thẩm mỹ, tôi có vấn đề tương tự (và đã nêu lên câu trả lời này). Tôi không nghĩ $ (cái này) tồn tại phương thức .data (). Câu trả lời của Avi Pinto quay trở lại yếu tố được chọn cho giá trị của nó và điều này hiệu quả với tôi (vì vậy tôi cũng ủng hộ Avi's).
tạm biệt

1
Điều này sẽ không hoạt động vì điều này! == $ ('mySelect'). Đây là một phiên bản cố định. var $selectStatus = $('.my-select'); $selectStatus.on('change', function () { var newStatus = $(this).val(); var oldStatus = $(this).data('pre'); }).data('pre', $selectStatus.val());
Capy

2
@Sinaologists dòng này đặt một giá trị cho tất cả các yếu tố "mySelect" $('mySelect').data('pre', $(this).val());Nó phải là: $('mySelect').each(function() { $(this).data('pre', $(this).val()); });Tôi không có đủ danh tiếng để chỉnh sửa câu trả lời: /
Abderrahim

8

Theo dõi giá trị bằng tay.

var selects = jQuery("select.track_me");

selects.each(function (i, element) {
  var select = jQuery(element);
  var previousValue = select.val();
  select.bind("change", function () {
    var currentValue = select.val();

    // Use currentValue and previousValue
    // ...

    previousValue = currentValue;
  });
});

Tôi không thể sử dụng phương pháp tiếp cận trên beacuse tôi đang có nhiều hộp chọn trong cùng một trang mà tôi phải đối phó.
Alpesh

1
Bạn không nói gì về nhiều nút chọn trong câu hỏi của bạn. Cập nhật câu trả lời của tôi để hỗ trợ nhiều hộp mặc dù.
Tháng 8 Lilleaas

1
câu trả lời tốt nhất. Tôi nghĩ giải pháp này tốt hơn so với việc sử dụng tiêu điểm () và thay đổi () vì nó dựa vào jquery để tương thích trình duyệt, sau đó thực hiện luồng ef chính xác của cả hai phương pháp
coorasse

@coorasse: luồng thực thi chính xác không bao giờ có thể khác nhau. Người dùng không bao giờ có thể thay đổi giá trị hộp chọn trước khi phần tử lấy nét. Điều đó đang được nói, không có gì sai với cách tiếp cận này :-)
Andy E

Từ quan điểm sử dụng 'đóng cửa', tôi không chắc liệu điều này có tốt hơn giải pháp 'tập trung' hay không.
James Poulose

8
 $("#dropdownId").on('focus', function () {
    var ddl = $(this);
    ddl.data('previous', ddl.val());
}).on('change', function () {
    var ddl = $(this);
    var previous = ddl.data('previous');
    ddl.data('previous', ddl.val());
});

Điều này đối với tôi chỉ có một sự điều chỉnh nhỏ trên bộ chọn dropdownId thay vì một, cảm ơn
malkoty

2
Sự kiện thay đổi có thể xảy ra mà không có sự tương tác của người dùng, vì vậy đây không phải là một sự
khôn ngoan

3

Tôi đang sử dụng sự kiện "trực tiếp", giải pháp của tôi về cơ bản giống với Dimitiar, nhưng thay vì sử dụng "tiêu điểm", giá trị trước đó của tôi được lưu trữ khi "nhấp chuột" được kích hoạt.

var previous = "initial prev value";
$("select").live('click', function () {
        //update previous value
        previous = $(this).val();
    }).change(function() {
        alert(previous); //I have previous value 
    });

2
Tôi sẽ không sử dụng cái này. Điều gì xảy ra nếu người dùng 'tab' vào phần tử chọn và sử dụng mũi tên bàn phím của mình để chọn một tùy chọn khác?
Christian Lundahl

@Perplexor có, nó sẽ không hoạt động với các khóa, nếu không, nó sẽ lưu trữ từng giá trị mỗi khi bạn nhấn phím. Điều này chỉ giả sử người dùng nhấp vào menu thả xuống. Vấn đề là 'sự kiện' trực tiếp sẽ không hoạt động với 'trọng tâm', tôi không biết giải pháp nào tốt hơn.
Cica Gustiani

Bạn có thể lưu trữ giá trị hiện tại tập trung vào một biến riêng biệt. Đây chỉ là từ đỉnh đầu của tôi nên tôi không chắc đây có phải là lý tưởng không.
Christian Lundahl

Nếu 'tiêu điểm' có thể hoạt động với sự kiện 'trực tiếp' thì nó sẽ hoàn hảo. Nhưng nếu bạn tự động tạo các menu thả xuống đó, bạn chỉ có thể sử dụng 'trực tiếp', đó là những gì tôi biết. Thật không may, 'tập trung' vào 'trực tiếp' không kích hoạt sự kiện để lưu trữ các giá trị mới, nhưng tôi không biết với câu
đố

sống là chết trong các phiên bản mới của jQuery! [ stackoverflow.com/questions/14354040/ cấp
remo

2

giữ giá trị thả xuống hiện được chọn với jquery đã chọn trong một biến toàn cục trước khi viết hàm hành động thả xuống 'thay đổi'. Nếu bạn muốn đặt giá trị trước đó trong hàm, bạn có thể sử dụng biến toàn cục.

//global variable
var previousValue=$("#dropDownList").val();
$("#dropDownList").change(function () {
BootstrapDialog.confirm(' Are you sure you want to continue?',
  function (result) {
  if (result) {
     return true;
  } else {
      $("#dropDownList").val(previousValue).trigger('chosen:updated');  
     return false;
         }
  });
});

1

Làm thế nào về việc sử dụng một sự kiện jQuery tùy chỉnh với giao diện loại đồng hồ góc cạnh;

// adds a custom jQuery event which gives the previous and current values of an input on change
(function ($) {
    // new event type tl_change
    jQuery.event.special.tl_change = {
        add: function (handleObj) {
            // use mousedown and touchstart so that if you stay focused on the
            // element and keep changing it, it continues to update the prev val
            $(this)
                .on('mousedown.tl_change touchstart.tl_change', handleObj.selector, focusHandler)
                .on('change.tl_change', handleObj.selector, function (e) {
                // use an anonymous funciton here so we have access to the
                // original handle object to call the handler with our args
                var $el = $(this);
                // call our handle function, passing in the event, the previous and current vals
                // override the change event name to our name
                e.type = "tl_change";
                handleObj.handler.apply($el, [e, $el.data('tl-previous-val'), $el.val()]);
            });
        },
        remove: function (handleObj) {
            $(this)
                .off('mousedown.tl_change touchstart.tl_change', handleObj.selector, focusHandler)
                .off('change.tl_change', handleObj.selector)
                .removeData('tl-previous-val');
        }
    };

    // on focus lets set the previous value of the element to a data attr
    function focusHandler(e) {
        var $el = $(this);
        $el.data('tl-previous-val', $el.val());
    }
})(jQuery);

// usage
$('.some-element').on('tl_change', '.delegate-maybe', function (e, prev, current) {
    console.log(e);         // regular event object
    console.log(prev);      // previous value of input (before change)
    console.log(current);   // current value of input (after change)
    console.log(this);      // element
});

1

Tôi biết đây là một chủ đề cũ, nhưng nghĩ rằng tôi có thể thêm vào một chút thêm. Trong trường hợp của tôi, tôi muốn chuyển văn bản, val và một số dữ liệu khác. Trong trường hợp này, tốt hơn là lưu trữ toàn bộ tùy chọn dưới dạng giá trị trước thay vì chỉ là giá trị.

Mã ví dụ dưới đây:

var $sel = $('your select');
$sel.data("prevSel", $sel.clone());
$sel.on('change', function () {
    //grab previous select
    var prevSel = $(this).data("prevSel");

    //do what you want with the previous select
    var prevVal = prevSel.val();
    var prevText = prevSel.text();
    alert("option value - " + prevVal + " option text - " + prevText)

    //reset prev val        
    $(this).data("prevSel", $(this).clone());
});

BIÊN TẬP:

Tôi quên thêm .clone () vào phần tử. không làm như vậy khi bạn cố gắng kéo lại các giá trị mà bạn sẽ kéo theo bản sao mới của lựa chọn thay vì trước đó. Sử dụng phương thức clone () lưu trữ một bản sao của lựa chọn thay vì một thể hiện của nó.


0

Chà, tại sao bạn không lưu trữ giá trị đã chọn hiện tại và khi mục được chọn thay đổi, bạn sẽ có giá trị cũ được lưu trữ? (và bạn có thể cập nhật lại nếu muốn)


Vâng, tôi không thể làm điều đó bởi vì trong trường hợp của tôi, tôi có nhiều hộp chọn trong cùng một trang. Và tiết kiệm giá trị ban đầu của tất cả ngay từ đầu sẽ quá khó khăn.
Alpesh

0

Sử dụng mã sau đây, tôi đã kiểm tra nó và nó hoạt động

var prev_val;
$('.dropdown').focus(function() {
    prev_val = $(this).val();
}).change(function(){
            $(this).unbind('focus');
            var conf = confirm('Are you sure want to change status ?');

            if(conf == true){
                //your code
            }
            else{
                $(this).val(prev_val);
                $(this).bind('focus');
                return false;
            }
});

0
(function() {

    var value = $('[name=request_status]').change(function() {
        if (confirm('You are about to update the status of this request, please confirm')) {
            $(this).closest('form').submit(); // submit the form
        }else {
            $(this).val(value); // set the value back
        }
    }).val();
})();

0

Tôi muốn đóng góp một lựa chọn khác để giải quyết vấn đề này; vì các giải pháp đề xuất ở trên không giải quyết được kịch bản của tôi.

(function()
    {
      // Initialize the previous-attribute
      var selects = $('select');
      selects.data('previous', selects.val());

      // Listen on the body for changes to selects
      $('body').on('change', 'select',
        function()
        {
          $(this).data('previous', $(this).val());
        }
      );
    }
)();

Cái này không dùng jQuery sao cho def. là một phụ thuộc ở đây, nhưng điều này có thể được điều chỉnh để hoạt động trong javascript thuần. (Thêm người nghe vào phần thân, kiểm tra xem mục tiêu ban đầu có phải là chức năng chọn, thực thi không, ...).

Bằng cách gắn trình nghe thay đổi vào phần thân, bạn có thể chắc chắn điều này sẽ kích hoạt sau các trình nghe cụ thể cho các lựa chọn, nếu không, giá trị của 'dữ liệu trước đó' sẽ bị ghi đè trước khi bạn có thể đọc nó.

Tất nhiên, điều này là giả sử rằng bạn thích sử dụng các trình nghe riêng biệt cho giá trị đặt trước và giá trị kiểm tra của bạn. Nó phù hợp ngay với mô hình trách nhiệm duy nhất.

Lưu ý: Điều này bổ sung chức năng 'trước' này cho tất cả các lựa chọn, vì vậy hãy chắc chắn tinh chỉnh các bộ chọn nếu cần.


0

Đây là một cải tiến về câu trả lời @thisisboris. Nó thêm một giá trị hiện tại vào dữ liệu, vì vậy mã có thể kiểm soát khi một biến được đặt thành giá trị hiện tại bị thay đổi.

(function()
{
    // Initialize the previous-attribute
    var selects = $( 'select' );
    $.each( selects, function( index, myValue ) {
        $( myValue ).data( 'mgc-previous', myValue.value );
        $( myValue ).data( 'mgc-current', myValue.value );  
    });

    // Listen on the body for changes to selects
    $('body').on('change', 'select',
        function()
        {
            alert('I am a body alert');
            $(this).data('mgc-previous', $(this).data( 'mgc-current' ) );
            $(this).data('mgc-current', $(this).val() );
        }
    );
})();

0

Giải pháp tốt nhất:

$('select').on('selectric-before-change', function (event, element, selectric) {
    var current = element.state.currValue; // index of current value before select a new one
    var selected = element.state.selectedIdx; // index of value that will be selected

    // choose what you need
    console.log(element.items[current].value);
    console.log(element.items[current].text);
    console.log(element.items[current].slug);
});

1
câu trả lời này dựa trên thư viện js "Chọn lọc" chứ không dựa trên jQuery hoặc javascript 'đơn giản'. Sự kiện là tốt nhất, nó không phù hợp với câu hỏi ban đầu và cũng không nói rằng người dùng cần cài đặt một cái gì đó khác để nó hoạt động
gad00

0

Có một số cách để đạt được kết quả mong muốn của bạn, đây là cách làm khiêm tốn của tôi:

Để phần tử giữ giá trị trước đó của nó, vì vậy hãy thêm một thuộc tính 'trướcValue'.

<select id="mySelect" previousValue=""></select>

Sau khi được khởi tạo, 'trướcValue' giờ đây có thể được sử dụng làm thuộc tính. Trong JS, để truy cập Giá trị trước của mục này, hãy chọn:

$("#mySelect").change(function() {console.log($(this).attr('previousValue'));.....; $(this).attr('previousValue', this.value);}

Sau khi bạn hoàn thành việc sử dụng 'trướcValue', hãy cập nhật thuộc tính thành giá trị hiện tại.


0

Tôi cần tiết lộ một div khác nhau dựa trên lựa chọn

Đây là cách bạn có thể làm điều đó với cú pháp jquery và es6

HTML

<select class="reveal">
    <option disabled selected value>Select option</option>
    <option value="value1" data-target="#target-1" >Option 1</option>
    <option value="value2" data-target="#target-2" >Option 2</option>
</select>
<div id="target-1" style="display: none">
    option 1
</div>
<div id="target-2" style="display: none">
    option 2
</div>

Mã não

$('select.reveal').each((i, element)=>{
    //create reference variable 
    let $option = $('option:selected', element)
    $(element).on('change', event => {
        //get the current select element
        let selector = event.currentTarget
        //hide previously selected target
        if(typeof $option.data('target') !== 'undefined'){
            $($option.data('target')).hide()
        }
        //set new target id
        $option = $('option:selected', selector)
        //show new target
        if(typeof $option.data('target') !== 'undefined'){
            $($option.data('target')).show()
        }
    })
})
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.