Değişiklikten önce seçme (açılır) değerinin elde edilmesi


237

Başlamak istediğim şey, <select>açılır menü her değiştiğinde, değişimden önce açılır menü değerini istiyorum. Ben jQuery 1.3.2 sürümünü kullanarak ve değişiklik olayı kullanarak ama oraya alıyorum değer değişiklikten sonra.

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

Şimdi diyelim ki onchange olayında yığını değiştirmek için değiştirdiğimde (şimdi yığın olarak değiştirdiğimde) My seçili olduğunu söyleyelim.

Bu nasıl başarılabilir?

Düzenleme: Benim durumumda aynı sayfada birden fazla seçim kutusu yaşıyorum ve hepsine aynı şeyi uygulamak istiyorum. Ayrıca tüm seçimlerim ajax aracılığıyla sayfa yüklendikten sonra eklenir.


1
Şunu

Yanıtlar:


434

İstediğinizi elde etmek için odak olayını değişiklik olayıyla birleştirin :

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

Çalışma örneği: http://jsfiddle.net/x5PKf/766


1
@Alpesh: Maalesef, jQuery 1.4.1 veya daha yenisini kullanmadığınız için, focus () öğesini focus ve değiştir olaylarıyla kullanamazsınız . Yapabileceğiniz tek şey, öğeler sayfaya eklendikten sonra komut dosyanızı bağlamak için ayarlamaktır.
Andy E

1
Teşekkürler zaten hem canlı ile bağladım ve başarıyla çalıştı. :)
Alpesh

4
Değişiklik işleyicinizdeki select öğesini de odaklamanız gerektiğini unutmayın, aksi takdirde tekrarlanan değer değişikliğinden sonra tetiklenmeyecektir
Alex

52
Bu çözüme katılmıyorum. Değeri bir kez değiştirirseniz çalışır ancak bir kez daha yaparsanız çalışmaz. Odağı kaybetmek için bir yere tıklamanız ve açılır menüye başka bir tıklamanız gerekiyor. Ben şunu tavsiye ederim: $ ("# dropdownId"). .val ());});
free4ride

5
@ free4ride, düzeltme $(this).blur();işlevinin sonunda aradığımı düzeltmek için
chiliNUT

135

lütfen bunun için global bir değişken kullanmayın - önceki değeri burada bulunan verilerde saklayın bir örnek: http://jsbin.com/uqupu3/2/edit

ref için kod:

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

sadece sayfada birçok seçiminizin olduğunu gördüm - bu yaklaşım sizin için de işe yarayacaktır çünkü her seçim için önceki değeri seçme verilerinde saklayacaksınız


jQuery.data burada iyi bir çözümdür. çözümünüzde, seçili öğelerin çok olması durumunda mükemmel bir etkiye sahip her seçim için bir kapak oluşturuyorsunuz
Avi Pinto

Endişem performans değildi ve işlev oluşturmanın jQuery.dataher zamankinden daha yavaş olduğuna ikna olmadım .
Ağustos Lilleaas

9
peki jQuery.data kullanmak için itirazınız nedir? Bildiğim kadarıyla jQuery kütüphane de dahili olarak kullanır ve kullanmanızı önerir
Avi Pinto

Kesinlikle jQuery Data kullanarak katılıyorum- hatırlattığınız için teşekkürler küresel var kullanmak üzereydim. Global var yanlış bir şey yok ama veri kullanmak daha özlü. Ama zincirleme odak ve daha sonra değişim de güzel :)
Piotr Kula

4
@ppumkin: Global değişkente kesinlikle yanlış olan bir şey var: Sadece birini destekliyor select! Kabul edilen cevap hepsiyle eşleştiği için kırılacaktır, selectsadece ilkinin değerini saklar. data olduğunu bunu yapmak için iyi bir yol. +1 :)
Gone Coding

86

Avi Pinto'nun jquery.data()

Odak kullanmak geçerli bir çözüm değildir. Seçenekleri ilk kez değiştirdiğinizde çalışır, ancak bu seçim öğesinde kalır ve "yukarı" veya "aşağı" tuşuna basarsanız. Odak olayından bir daha geçmeyecek.

Yani çözüm daha çok aşağıdaki gibi olmalı,

//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
Harika bir çözüm, seçilen cevaptan çok daha iyi!
TJL

2
İkinci bölüm iyi çalışıyor ancak ilk bölüm veri niteliğini ayarlamıyor. Herhangi bir fikir?
Sinaestetik

1
@Sinaestetik, aynı sorunu yaşadım (ve zaten bu cevabı iptal ettim). $ (This) 'in .data () yönteminden sağ çıktığını düşünmüyorum. Avi Pinto'nun cevabı, değeri için seçme unsuruna geri dönüyor ve bu benim için çalıştı (bu yüzden Avi'nin de desteğini aldım).
goodeye

1
Bu bundan sonra çalışmayacak! == $ ('mySelect'). İşte sabit bir sürüm. var $selectStatus = $('.my-select'); $selectStatus.on('change', function () { var newStatus = $(this).val(); var oldStatus = $(this).data('pre'); }).data('pre', $selectStatus.val());
Capy

2
@Sinaesthetic bu satır tüm "mySelect" öğelerine bir değer ayarlar. $('mySelect').data('pre', $(this).val());Şöyle olmalıdır: $('mySelect').each(function() { $(this).data('pre', $(this).val()); });Cevabı düzenlemek için yeterli itibarım yok: /
Abderrahim

8

Değeri elle izleyin.

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

Yukarıdaki yaklaşımı kullanamıyorum çünkü aynı sayfada benimle uğraşmak zorunda olduğum birden fazla seçim kutusu yaşıyorum.
Alpesh

1
Sorunuzdaki çoklu seçim düğmeleri hakkında hiçbir şey söylemediniz. Yanıtımı birden çok kutuyu destekleyecek şekilde güncelledi.
Ağustos Lilleaas

1
en iyi cevap. Ben bu çözüm usign focus () ve change () 'dan daha iyi olduğunu düşünüyorum çünkü tarayıcı uyumluluğu için jquery güveniyor o zaman her iki yöntemin de doğru akış ef yürütme
coorasse 15

@coorasse: doğru yürütme akışı asla farklı olamazdı. Seçme kutuları değeri , öğe odaklanmadan önce kullanıcı tarafından asla değiştirilemez . Olduğu söyleniyor, bu yaklaşımda da yanlış bir şey yok :-)
Andy E

'Kapatma' kullanımı açısından, bunun 'odak' çözümünden daha iyi olup olmadığından emin değilim.
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());
});

Bu benim için çalıştı sadece hafif düzeltme açılan
seçimde

2
Değişim olayı kullanıcı etkileşimi olmadan gerçekleşebilir, bu yüzden bu bir beyin değildir
qdev

3

Olay "canlı" kullanıyorum, çözümüm temel olarak Dimitiar ile benzerdir, ancak "odak" yerine "tıklama" tetiklendiğinde önceki değerim saklanır.

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

2
Bunu kullanmam. Kullanıcı seçme öğesine 'sekerse' ve farklı bir seçenek seçmek için klavye oklarını kullanırsa ne olur?
Christian Lundahl

@Perplexor evet, tuşlarla çalışmaz, aksi takdirde tuşa her bastığınızda her değeri saklar. Bu yalnızca kullanıcının açılır menüyü tıkladığını varsayar. Sorun 'canlı' olay 'odak' ile çalışmaz, daha iyi bir çözüm bilmiyorum.
Cica Gustiani

Geçerli değeri odakta ayrı bir değişkene kaydedebilirsiniz. Bu sadece başımın üstünden, bu yüzden bunun ideal olup olmadığından emin değilim.
Christian Lundahl

'Odaklanma' 'canlı' etkinlikle çalışabiliyorsa mükemmel olur. Ancak bu açılır menüleri dinamik olarak oluşturursanız, yalnızca 'canlı' kullanabilirsiniz, bildiğim budur. 'Canlı' odak 'maalesef yeni değerleri saklamak için etkinliği tetiklemiyor, ancak yeni jquery ile bilmiyorum
Cica Gustiani

live jQuery yeni sürümlerinde öldü! [ stackoverflow.com/questions/14354040/…
remo

2

'değiştiğinde' eylem işlevini yazmadan önce seçili jquery ile seçili olan açılır değeri global bir değişkende tutar. İşlevde önceki değeri ayarlamak istiyorsanız genel değişkeni kullanabilirsiniz.

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

Açısal saat türü arabirimiyle özel bir jQuery olayı kullanmaya ne dersiniz;

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

Bu eski bir iplik olduğunu biliyorum, ama biraz ekstra ekleyebilirsiniz düşündüm. Benim durumumda, metin, val ve diğer bazı verileri attr. Bu durumda tüm seçeneği sadece val yerine bir prev değeri olarak saklamak daha iyidir.

Aşağıdaki örnek kod:

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

DÜZENLE:

Elemana .clone () eklemeyi unuttum. değerleri geri çekmeye çalıştığınızda, bir öncekinden ziyade seçimin yeni kopyasını çekersiniz. Clone () yönteminin kullanılması, select öğesinin kopyası yerine bir kopyasını depolar.


0

Peki, neden seçili değeri saklamıyorsunuz ve seçilen öğe değiştirildiğinde eski değerin kaydedilmesini sağlayacaksınız? (ve istediğiniz gibi tekrar güncelleyebilirsiniz)


Peki bunu yapamam çünkü benim durumumda aynı sayfada birden fazla seçim kutusu yaşıyorum. Ve başlangıçta herkesin başlangıç ​​değerini kaydetmek çok yorucu olacaktır.
Alpesh

0

Aşağıdaki kodu kullanın, test ettim ve çalışma

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

Bu sorunu çözmek için başka bir seçeneğe katkıda bulunmak istiyorum; çünkü yukarıda önerilen çözümler benim senaryomu çözmedi.

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

Bu jQuery kullanır böylece def. burada bir bağımlılık, ancak bu saf javascript çalışmak için adapte edilebilir. (Gövdeye bir dinleyici ekleyin, orijinal hedefin bir seçim olup olmadığını kontrol edin, işlevi çalıştırın ...).

Değişiklik dinleyicisini gövdeye ekleyerek, seçimler için belirli dinleyicilerden sonra bunun tetikleneceğinden emin olabilirsiniz , aksi takdirde 'önce veri' değerinin üzerine yazmadan önce yazılır.

Bu elbette set-setiniz ve kontrol-değeriniz için ayrı dinleyiciler kullanmayı tercih ettiğiniz varsayılmaktadır. Tek sorumluluk modeline tam olarak uyuyor.

Not: Bu, bu 'önceki' işlevselliği tüm seçimlere ekler , bu nedenle gerekirse seçicilerin ince ayarını yaptığınızdan emin olun.


0

Bu @ thisisboris cevabı üzerinde bir gelişme. Verilere bir akım değeri ekler, böylece kod, geçerli değere ayarlanan bir değişkenin ne zaman değiştirileceğini kontrol edebilir.

(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

En iyi çözüm:

$('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
bu cevap "düz" jQuery veya javascript değil, "Selectric" js kütüphanesine dayanır. Satışlardaki en iyisi, orijinal soruya uymuyor veya kullanıcının çalışması için başka bir şey yüklemesi gerektiğini
söylemiyor

0

İstediğiniz sonucu elde etmenin birkaç yolu vardır, bu benim alçakgönüllü yöntemim:

Öğenin önceki değerini tutmasına izin verin, bu yüzden 'previousValue' niteliğini ekleyin.

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

Başlatıldıktan sonra, 'previousDeğeri' artık bir nitelik olarak kullanılabilir. JS'de, bu seçeneğin öncekiDeğerine erişmek için:

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

'PreviousValue' kullanmayı tamamladıktan sonra, niteliği geçerli değere güncelleyin.


0

Seçime göre farklı bir div açığa çıkarmam gerekiyordu

Jquery ve es6 sözdizimi ile bu şekilde yapabilirsiniz

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()
        }
    })
})
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.