Mendapatkan nilai pilih (dropdown) sebelum berubah


237

Hal yang ingin saya capai adalah setiap kali <select>dropdown diubah, saya ingin nilai dropdown sebelum perubahan. Saya menggunakan versi 1.3.2 dari jQuery dan menggunakan pada acara perubahan tetapi nilai yang saya dapatkan di sana adalah setelah perubahan.

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

Katakanlah saat ini opsi Saya dipilih sekarang ketika saya mengubahnya untuk menumpuk di acara onchange (yaitu ketika saya mengubahnya untuk menumpuk) Saya ingin itu nilai sebelumnya yaitu yang saya harapkan dalam kasus ini.

Bagaimana ini bisa dicapai?

Sunting: Dalam kasus saya, saya memiliki beberapa kotak pilih di halaman yang sama dan ingin hal yang sama diterapkan pada semuanya. Juga semua pilih saya dimasukkan setelah memuat halaman melalui ajax.


1
Sudahkah Anda memeriksanya: stackoverflow.com/questions/1983535/…
Rajat

Jawaban:


434

Gabungkan acara fokus dengan acara perubahan untuk mencapai apa yang Anda inginkan:

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

Contoh kerja: http://jsfiddle.net/x5PKf/766


1
@Alpesh: Sayangnya tidak, karena Anda tidak menggunakan jQuery 1.4.1 atau lebih baru, Anda tidak dapat menggunakan live () dengan fokus dan mengubah acara. Satu-satunya hal yang dapat Anda lakukan adalah menyesuaikan skrip Anda untuk mengikat setelah elemen dimasukkan ke halaman.
Andy E

1
Terima kasih saya sudah mengikat keduanya dengan live dan berhasil. :)
Alpesh

4
Perhatikan bahwa Anda juga harus memfokuskan elemen pilih di penangan perubahan Anda, jika tidak maka tidak akan dipicu setelah perubahan nilai berulang
Alex

52
Saya tidak setuju dengan solusi ini. Jika Anda mengubah nilai setelah itu akan berfungsi tetapi jika Anda melakukannya sekali lagi itu tidak akan berhasil. Anda harus mengklik di suatu tempat untuk kehilangan fokus dan klik lain pada dropdown. Saya sarankan: $ ("# dropdownId"). Pada ('ubah', fungsi () {var ddl = $ (ini); var sebelumnya = ddl.data ('sebelumnya'); ddl.data ('sebelumnya', ddl .val ());});
free4ride

5
@ free4ride, untuk memperbaikinya saya baru saja menelepon $(this).blur();di akhir fungsi perubahan
chiliNUT

135

tolong jangan gunakan global var untuk ini - simpan nilai prev pada data di sini adalah contoh: http://jsbin.com/uqupu3/2/edit

kode untuk 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());
  });
});

hanya melihat bahwa Anda memiliki banyak pilihan pada halaman - pendekatan ini juga akan bekerja untuk Anda karena untuk setiap pilih Anda akan menyimpan nilai sebelumnya pada data pilih


jQuery.data adalah solusi yang bagus di sini. pada solusi Anda, Anda sedang membuat penutupan untuk setiap pilih yang memiliki dampak perf jika ada banyak elemen pilih
Avi Pinto

Kekhawatiran saya bukan pada kinerja, dan saya tidak yakin bahwa membuat fungsi lebih lambat daripada yang lainnya jQuery.data.
Agustus Lilleaas

9
jadi apa keberatan Anda untuk menggunakan jQuery.data? sejauh yang saya tahu perpustakaan jQuery juga menggunakannya secara internal, dan merekomendasikan untuk menggunakannya
Avi Pinto

Pasti setuju dengan menggunakan Data jQuery - terima kasih untuk mengingatkan saya bahwa saya akan menggunakan var global .. Tidak ada yang salah dengan var global tetapi menggunakan data lebih ringkas. Tapi fokus chaining dan kemudian berubah juga bagus :)
Piotr Kula

4
@ ppkinkin: Satu hal yang pasti salah dengan variabel global: Itu hanya mendukung satu select! Jawaban yang diterima akan rusak karena cocok dengan semua selecttetapi hanya menyimpan nilai yang pertama. data adalah cara yang lebih baik untuk melakukannya. +1 :)
Hilang Pengkodean

86

Saya memilih solusi Avi Pinto yang digunakan jquery.data()

Menggunakan fokus bukanlah solusi yang valid. Ini bekerja pada saat pertama kali Anda mengubah opsi, tetapi jika Anda tetap pada elemen pilih itu, dan tekan tombol "atas" atau "bawah". Itu tidak akan melalui acara fokus lagi.

Jadi solusinya harus lebih mirip seperti berikut,

//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
Solusi hebat, jauh lebih baik daripada jawaban yang dipilih!
TJL

2
Bagian kedua berfungsi dengan baik tetapi bagian pertama tidak mengatur atribut data. Ada ide?
Sinaesthetic

1
@Sinestetik, saya memiliki masalah yang sama (dan sudah mengangkat jawaban ini). Saya tidak berpikir $ (ini) selamat dari metode. Data (). Jawaban Avi Pinto kembali ke elemen pilih untuk nilainya, dan ini berhasil bagi saya (jadi saya juga memutakhirkan Avi).
selamat tinggal

1
Ini Tidak akan berfungsi sejak ini! == $ ('mySelect'). Ini adalah versi tetap. var $selectStatus = $('.my-select'); $selectStatus.on('change', function () { var newStatus = $(this).val(); var oldStatus = $(this).data('pre'); }).data('pre', $selectStatus.val());
Capy

2
@Sinesthetic baris ini menetapkan satu nilai untuk semua elemen "mySelect" $('mySelect').data('pre', $(this).val());Seharusnya: $('mySelect').each(function() { $(this).data('pre', $(this).val()); });Saya tidak punya cukup reputasi untuk mengedit jawaban: /
Abderrahim

8

Lacak nilainya dengan tangan.

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

Saya tidak dapat menggunakan pendekatan di atas karena saya memiliki beberapa kotak pilih di halaman yang sama dengan siapa saya harus berurusan.
Alpesh

1
Anda tidak mengatakan apa-apa tentang beberapa tombol pilih dalam pertanyaan Anda. Diperbarui jawaban saya untuk mendukung beberapa kotak.
Agustus Lilleaas

1
jawaban Terbaik. Saya pikir solusi ini lebih baik daripada fokus usign () dan perubahan () karena ini bergantung pada jquery untuk kompatibilitas browser, kemudian aliran yang benar dari kedua metode
coorasse

@ campasse: aliran eksekusi yang benar tidak akan pernah berbeda. Nilai kotak pilih tidak akan pernah bisa diubah oleh pengguna sebelum elemen mengambil fokus. Meski begitu, tidak ada yang salah dengan pendekatan ini :-)
Andy E

Dari sudut pandang penggunaan 'penutupan', saya tidak yakin apakah ini lebih baik daripada solusi 'fokus'.
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());
});

Ini bekerja untuk saya hanya sedikit koreksi pada pemilih dropdownId pada bukan, terima kasih
malkoty

2
Perubahan acara dapat terjadi tanpa interaksi pengguna, jadi ini bukan brainer
qdev

3

Saya menggunakan acara "langsung", solusi saya pada dasarnya serupa dengan Dimitiar, tetapi alih-alih menggunakan "fokus", nilai saya sebelumnya disimpan ketika "klik" dipicu.

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

2
Saya tidak akan menggunakan ini. Bagaimana jika pengguna 'tab' ke elemen pilih dan menggunakan panah keyboard-nya untuk memilih opsi yang berbeda?
Christian Lundahl

@Perplexor ya, itu tidak akan berfungsi dengan kunci, jika tidak akan menyimpan setiap nilai setiap kali Anda menekan tombol. Ini hanya mengasumsikan pengguna mengklik menu drop down. Masalahnya adalah acara 'langsung' tidak bekerja dengan 'fokus', saya tidak tahu solusi yang lebih baik
Cica Gustiani

Anda bisa menyimpan nilai saat ini pada fokus ke variabel yang terpisah. Ini hanya dari atas kepala saya, jadi saya tidak yakin apakah ini ideal.
Christian Lundahl

Jika 'fokus' dapat bekerja dengan acara 'langsung' itu akan sempurna. Tetapi jika Anda secara dinamis membuat menu drop down itu, Anda hanya dapat menggunakan 'hidup', itulah yang saya tahu. 'Fokus' pada 'langsung' tidak memicu acara untuk menyimpan nilai-nilai baru, sayangnya, tapi saya tidak tahu dengan jquery baru
Cica Gustiani

live sudah mati di versi baru jQuery! [ stackoverflow.com/questions/14354040/…
remo

2

menjaga nilai drop-down yang dipilih saat ini dengan jquery yang dipilih dalam variabel global sebelum menulis fungsi aksi drop-down 'saat perubahan'. Jika Anda ingin menetapkan nilai sebelumnya dalam fungsi Anda dapat menggunakan variabel global.

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

Bagaimana dengan menggunakan acara jQuery khusus dengan antarmuka jenis jam tangan sudut;

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

Saya tahu ini adalah utas lama, tetapi saya pikir saya dapat menambahkan sedikit tambahan. Dalam kasus saya, saya ingin menyampaikan teks, val, dan beberapa data lainnya. Dalam hal ini lebih baik menyimpan seluruh opsi sebagai nilai prev daripada hanya val.

Contoh kode di bawah ini:

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

EDIT:

Saya lupa menambahkan .clone () ke elemen. dalam tidak melakukannya ketika Anda mencoba untuk menarik kembali nilai-nilai yang Anda akhirnya menarik dalam salinan yang dipilih daripada yang sebelumnya. Menggunakan metode clone () menyimpan salinan pilih bukan turunannya.


0

Nah, mengapa Anda tidak menyimpan nilai yang dipilih saat ini, dan ketika item yang dipilih diubah, Anda akan memiliki nilai lama disimpan? (dan Anda dapat memperbaruinya lagi sesuai keinginan)


Yah saya tidak bisa melakukan itu karena dalam kasus saya saya memiliki beberapa kotak pilih di halaman yang sama. Dan menyimpan nilai awal dari semua di awal akan terlalu sulit.
Alpesh

0

Gunakan kode berikut, saya telah mengujinya dan berfungsi

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

Saya ingin berkontribusi opsi lain untuk menyelesaikan masalah ini; karena solusi yang diusulkan di atas tidak menyelesaikan skenario saya.

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

Ini tidak menggunakan jQuery sehingga def. adalah ketergantungan di sini, tetapi ini dapat disesuaikan untuk bekerja di javascript murni. (Tambahkan pendengar ke badan, periksa apakah target awal adalah fungsi pilih, jalankan, ...).

Dengan melampirkan pendengar perubahan ke badan, Anda dapat yakin ini akan muncul setelah pendengar tertentu untuk memilih, jika tidak nilai 'data-sebelumnya' akan ditimpa sebelum Anda bahkan dapat membacanya.

Ini tentu saja dengan asumsi bahwa Anda lebih suka menggunakan pendengar yang terpisah untuk nilai set-sebelumnya dan nilai cek Anda. Ini cocok dengan pola tanggung jawab tunggal.

Catatan: Ini menambahkan fungsionalitas 'sebelumnya' ini ke semua pilihan , jadi pastikan untuk menyelaraskan pemilih jika diperlukan.


0

Ini merupakan peningkatan pada jawaban @thisisboris. Ini menambahkan nilai saat ini ke data, sehingga kode dapat mengontrol ketika variabel yang diatur ke nilai saat ini diubah.

(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

Solusi terbaik:

$('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
jawaban ini didasarkan pada pustaka js "Selectric", dan bukan pada jQuery atau javascript 'biasa'. Walaupun itu yang terbaik, itu tidak sesuai dengan pertanyaan awal dan juga tidak mengatakan bahwa pengguna perlu menginstal sesuatu yang lain agar bisa berfungsi
gadget00

0

Ada beberapa cara untuk mencapai hasil yang Anda inginkan, ini cara saya yang sederhana untuk melakukannya:

Biarkan elemen menyimpan nilai sebelumnya, jadi tambahkan atribut 'priorValue'.

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

Setelah diinisialisasi, 'Nilai sebelumnya' sekarang dapat digunakan sebagai atribut. Di JS, untuk mengakses Nilai sebelumnya dari ini pilih:

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

Setelah selesai menggunakan 'Nilai sebelumnya', perbarui atribut ke nilai saat ini.


0

Saya perlu mengungkapkan div yang berbeda berdasarkan seleksi

Ini adalah bagaimana Anda dapat melakukannya dengan sintaks jquery dan 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>

JS

$('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()
        }
    })
})
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.