รับค่าของการเลือก (ดร็อปดาวน์) ก่อนการเปลี่ยนแปลง


237

สิ่งที่ฉันต้องการบรรลุคือเมื่อใดก็ตามที่<select>มีการเปลี่ยนแปลงแบบเลื่อนลงฉันต้องการค่าของแบบเลื่อนลงก่อนการเปลี่ยนแปลง ฉันใช้ jQuery เวอร์ชั่น 1.3.2 และใช้กับเหตุการณ์การเปลี่ยนแปลง แต่ค่าที่ฉันได้รับที่นั่นคือหลังจากการเปลี่ยนแปลง

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

ให้บอกว่าตัวเลือกในปัจจุบันของฉันถูกเลือกตอนนี้เมื่อฉันเปลี่ยนเป็นสแต็คในเหตุการณ์ onchange (เช่นเมื่อฉันเปลี่ยนเป็นสแต็ค) ฉันต้องการมันเป็นค่าก่อนหน้าเช่นที่ฉันคาดไว้ในกรณีนี้

จะประสบความสำเร็จได้อย่างไร?

แก้ไข:ในกรณีของฉันฉันมีหลายกล่องที่เลือกในหน้าเดียวกันและต้องการสิ่งเดียวกันที่จะนำไปใช้กับพวกเขาทั้งหมด นอกจากนี้การเลือกทั้งหมดของฉันจะถูกแทรกหลังจากโหลดหน้าเว็บผ่าน ajax


1
คุณได้ตรวจสอบสิ่งนี้แล้ว: stackoverflow.com/questions/1983535/…
Rajat

คำตอบ:


434

รวมกิจกรรมการโฟกัสเข้ากับกิจกรรมการเปลี่ยนแปลงเพื่อให้บรรลุสิ่งที่คุณต้องการ:

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

ตัวอย่างการทำงาน: http://jsfiddle.net/x5PKf/766


1
@Alpesh: ไม่ใช่เพราะคุณไม่ได้ใช้ jQuery 1.4.1 หรือใหม่กว่าคุณจะไม่สามารถใช้live ()ด้วยการโฟกัสและเปลี่ยนกิจกรรมได้ สิ่งเดียวที่คุณทำได้คือปรับสคริปต์ของคุณให้เชื่อมโยงหลังจากที่องค์ประกอบถูกแทรกลงในหน้า
Andy E

1
ขอบคุณฉันได้ผูกทั้งกับการแสดงสดและมันใช้งานได้สำเร็จ :)
Alpesh

4
โปรดทราบว่าคุณควรเน้นที่องค์ประกอบที่เลือกในตัวจัดการการเปลี่ยนแปลงของคุณมิฉะนั้นจะไม่ถูกเรียกใช้หลังจากการเปลี่ยนค่าซ้ำ ๆ
Alex

52
ฉันไม่เห็นด้วยกับวิธีนี้ หากคุณเปลี่ยนค่าเมื่อมันจะทำงาน แต่ถ้าคุณทำมันอีกครั้งมันจะไม่ คุณต้องคลิกที่ใดที่หนึ่งเพื่อคลายโฟกัสและคลิกอีกครั้งที่เมนูแบบเลื่อนลง ฉันขอแนะนำ: $ ("# dropdownId"). on ('เปลี่ยน', ฟังก์ชั่น () {var ddl = $ (นี้); var ก่อนหน้า = ddl.data ('ก่อนหน้า'); ddl.data ('ก่อนหน้า', ddl .val ());});
free4ride

5
@ free4ride เพื่อแก้ไขว่าฉันเพิ่งโทรไป$(this).blur();ที่จุดสิ้นสุดของฟังก์ชั่นการเปลี่ยนแปลง
chiliNUT

135

โปรดอย่าใช้ var ส่วนกลางสำหรับสิ่งนี้ - เก็บค่า prev ที่ข้อมูลที่นี่คือตัวอย่าง: http://jsbin.com/uqupu3/2/edit

รหัสสำหรับการอ้างอิง:

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

เพิ่งเห็นว่าคุณมีตัวเลือกมากมายในหน้า - วิธีการนี้จะใช้ได้ผลสำหรับคุณเนื่องจากแต่ละตัวเลือกคุณจะเก็บค่า prev บนข้อมูลของตัวเลือก


jQuery.data เป็นทางออกที่ดีที่นี่ ในการแก้ปัญหาของคุณคุณกำลังสร้างการปิดตัวเลือกแต่ละตัวซึ่งมีผลกระทบอย่างสมบูรณ์หากมีองค์ประกอบที่เลือกมากมาย
Avi Pinto

ความกังวลของฉันไม่ได้มีประสิทธิภาพและฉันไม่เชื่อว่าการสร้างฟังก์ชั่นจะช้ากว่าjQuery.dataอย่างไรก็ตาม
สิงหาคม Lilleaas

9
ดังนั้นคุณคัดค้านการใช้ jQuery.data คืออะไร? เท่าที่ฉันรู้ไลบรารี jQuery ยังใช้ภายในและแนะนำให้ใช้
Avi Pinto

เห็นด้วยอย่างแน่นอนกับการใช้ข้อมูล jQuery- ขอบคุณสำหรับการเตือนฉันฉันกำลังจะใช้ var ทั่วโลก .. ไม่มีอะไรผิดปกติกับ var ทั่วโลก แต่การใช้ข้อมูลนั้นรัดกุมกว่า แต่การผูกมัดที่มุ่งเน้นและจากนั้นการเปลี่ยนแปลงก็ดี :)
Piotr Kula

4
@ppumkin: มีสิ่งหนึ่งที่ผิดปกติกับตัวแปรทั่วโลก: รองรับเพียงหนึ่งเท่านั้นselect! คำตอบที่ยอมรับจะแตกเมื่อตรงกับทั้งหมดselectแต่เก็บเฉพาะค่าของคำตอบแรกเท่านั้น data เป็นวิธีที่ดีกว่าที่จะทำ +1 :)
ไปที่เข้ารหัส

86

ฉันไปหาทางออกของ Avi Pinto ที่ใช้ jquery.data()

การใช้โฟกัสไม่ใช่โซลูชันที่ถูกต้อง มันทำงานในครั้งแรกที่คุณเปลี่ยนตัวเลือก แต่ถ้าคุณยังคงอยู่ในองค์ประกอบที่เลือกนั้นและกดปุ่ม "ขึ้น" หรือ "ลง" มันจะไม่ผ่านเหตุการณ์โฟกัสอีกครั้ง

ดังนั้นการแก้ปัญหาควรมีลักษณะมากขึ้นดังต่อไปนี้

//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
ทางออกที่ยอดเยี่ยมดีกว่าคำตอบที่เลือก!
TJL

2
ส่วนที่สองทำงานได้ดี แต่ส่วนแรกไม่ได้ตั้งค่าแอตทริบิวต์ข้อมูล ความคิดใด ๆ
Sinaesthetic

1
@Sinaesthetic ฉันมีปัญหาเดียวกัน (และเลิกตอบแล้ว) ฉันไม่คิดว่า $ (สิ่งนี้) จะอยู่รอดได้ในวิธีการ. data () คำตอบของ Avi Pinto กลับไปที่องค์ประกอบที่เลือกสำหรับค่าของมันและสิ่งนี้ใช้ได้กับฉัน (ดังนั้นฉันจึงสนับสนุน Avi ด้วยเช่นกัน)
goodeye

1
สิ่งนี้จะไม่ทำงานตั้งแต่นี้! == $ ('mySelect') นี่คือรุ่นที่แน่นอน var $selectStatus = $('.my-select'); $selectStatus.on('change', function () { var newStatus = $(this).val(); var oldStatus = $(this).data('pre'); }).data('pre', $selectStatus.val());
Capy

2
@Sinaesthetic บรรทัดนี้ตั้งค่าหนึ่งค่าสำหรับองค์ประกอบ "mySelect" ทั้งหมด$('mySelect').data('pre', $(this).val());ควรเป็น: $('mySelect').each(function() { $(this).data('pre', $(this).val()); });ฉันไม่มีชื่อเสียงเพียงพอที่จะแก้ไขคำตอบ: /
Abderrahim

8

ติดตามมูลค่าด้วยมือ

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

ฉันไม่สามารถใช้วิธีการข้างต้นได้เพราะฉันมีกล่องเลือกหลายกล่องในหน้าเดียวกันกับที่ฉันต้องจัดการ
Alpesh

1
คุณไม่ได้พูดอะไรเกี่ยวกับปุ่มเลือกหลายปุ่มในคำถามของคุณ อัปเดตคำตอบของฉันเพื่อรองรับหลายกล่อง
August Lilleaas

1
คำตอบที่ดีที่สุด ผมคิดว่าการแก้ปัญหานี้จะดีกว่าโฟกัส usign () และการเปลี่ยนแปลง () 'สาเหตุที่มันอาศัยอยู่กับ jQuery เข้ากันได้เบราว์เซอร์ raither แล้วการดำเนินการไหลของ EF ที่ถูกต้องของทั้งสองวิธี
coorasse

@coorasse: การไหลเวียนที่ถูกต้องของการดำเนินการจะไม่แตกต่างกัน ผู้ใช้ไม่สามารถเปลี่ยนค่าของกล่องที่เลือกก่อนที่องค์ประกอบจะโฟกัส ที่ถูกกล่าวว่ามีอะไรผิดปกติกับวิธีการนี้อย่างใดอย่างหนึ่ง :-)
แอนดี้ E

จากมุมมองของการใช้งาน 'ปิด' ฉันไม่แน่ใจว่านี่ดีกว่าโซลูชัน 'โฟกัส' หรือไม่
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());
});

สิ่งนี้ใช้งานได้สำหรับฉันเท่านั้นการแก้ไขเล็กน้อยบนตัวเลือกแบบเลื่อนลงมันเปิดแทนหนึ่งขอบคุณ
malkoty

2
เหตุการณ์การเปลี่ยนแปลงสามารถเกิดขึ้นได้โดยไม่ต้องมีการโต้ตอบกับผู้ใช้ดังนั้นนี่ไม่ใช่เกมง่ายๆ
qdev

3

ฉันกำลังใช้เหตุการณ์ "สด" โซลูชันของฉันก็คล้ายกับ Dimitiar แต่แทนที่จะใช้ "โฟกัส" ค่าก่อนหน้าของฉันจะถูกเก็บไว้เมื่อมีการเรียกใช้ "คลิก"

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

2
ฉันจะไม่ใช้สิ่งนี้ จะเกิดอะไรขึ้นหากผู้ใช้ 'แท็บ' ลงในองค์ประกอบที่เลือกและใช้ลูกศรบนแป้นพิมพ์เพื่อเลือกตัวเลือกอื่น
Christian Lundahl

@Perplexor ใช่มันจะไม่ทำงานกับคีย์มิฉะนั้นมันจะเก็บค่าแต่ละค่าทุกครั้งที่คุณกดปุ่ม เพียงถือว่าผู้ใช้คลิกเมนูแบบเลื่อนลง ปัญหาคือเหตุการณ์ 'สด' จะไม่ทำงานกับ 'โฟกัส' ฉันไม่ทราบวิธีแก้ไขที่ดีกว่า
Cica Gustiani

คุณสามารถเก็บค่าปัจจุบันของการโฟกัสลงในตัวแปรแยกต่างหาก นี่เป็นเพียงส่วนหัวของฉันดังนั้นฉันไม่แน่ใจว่านี่จะเหมาะ
Christian Lundahl

หาก 'โฟกัส' สามารถทำงานกับเหตุการณ์ 'สด' มันจะสมบูรณ์แบบ แต่ถ้าคุณสร้างเมนูแบบเลื่อนลงคุณสามารถใช้ 'สด' เท่านั้นนั่นคือสิ่งที่ฉันรู้ 'โฟกัส' บน 'สด' ไม่ได้เรียกให้เหตุการณ์เก็บค่าใหม่โชคไม่ดี แต่ฉันไม่รู้ด้วย jQuery ใหม่
Cica Gustiani

live นั้นตายแล้วใน jQuery เวอร์ชันใหม่! [ stackoverflow.com/questions/14354040/...
Remo

2

เก็บค่าแบบหล่นลงที่เลือกไว้ในปัจจุบันด้วย jquery ที่เลือกไว้ในตัวแปรส่วนกลางก่อนที่จะเขียนฟังก์ชั่นการกระทำแบบหล่นลง 'เมื่อเปลี่ยน' หากคุณต้องการตั้งค่าก่อนหน้าในฟังก์ชั่นคุณสามารถใช้ตัวแปรทั่วโลก

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

วิธีการเกี่ยวกับการใช้เหตุการณ์ jQuery ที่กำหนดเองด้วยอินเทอร์เฟซชนิดนาฬิกาเชิงมุม

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

ฉันรู้ว่านี่เป็นหัวข้อเก่า แต่คิดว่าฉันอาจเพิ่มพิเศษเล็กน้อย ในกรณีของฉันฉันต้องการส่งต่อข้อความวาลและข้อมูลอื่น ๆ ในกรณีนี้มันจะดีกว่าที่จะเก็บตัวเลือกทั้งหมดเป็นค่าก่อนหน้าแทนที่จะเป็นแค่ค่าวาล

รหัสตัวอย่างด้านล่าง:

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

แก้ไข:

ฉันลืมเพิ่ม. clone () ลงในองค์ประกอบ ในการไม่ทำเช่นนั้นเมื่อคุณพยายามที่จะดึงกลับค่าที่คุณท้ายดึงในสำเนาใหม่ของการเลือกมากกว่าก่อนหน้า การใช้เมธอด clone () จะเก็บสำเนาของตัวเลือกแทนอินสแตนซ์ของมัน


0

ทำไมคุณไม่เก็บค่าที่เลือกไว้ในปัจจุบันและเมื่อรายการที่เลือกเปลี่ยนไปคุณจะต้องเก็บค่าเก่าไว้ (และคุณสามารถอัปเดตอีกครั้งตามที่คุณต้องการ)


ฉันไม่สามารถทำได้เพราะในกรณีของฉันฉันมีหลายกล่องที่เลือกในหน้าเดียวกัน และการบันทึกค่าเริ่มต้นของทุกคนที่จุดเริ่มต้นจะเป็นอันตรายมากเกินไป
Alpesh

0

ใช้รหัสต่อไปนี้ฉันได้ทดสอบและใช้งานได้แล้ว

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

ฉันต้องการมีส่วนร่วมในการแก้ปัญหานี้อีกทางเลือกหนึ่ง; เนื่องจากโซลูชันที่เสนอข้างต้นไม่สามารถแก้สถานการณ์ของฉันได้

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

สิ่งนี้ใช้ jQuery เพื่อกำหนดว่า คือการพึ่งพาที่นี่ แต่สามารถปรับให้ทำงานในจาวาสคริปต์บริสุทธิ์ (เพิ่มผู้ฟังให้กับร่างกายตรวจสอบว่าเป้าหมายดั้งเดิมเป็นตัวเลือกดำเนินการฟังก์ชั่น ... )

ด้วยการแนบฟังการเปลี่ยนแปลงเข้ากับร่างกายคุณสามารถมั่นใจได้ว่าสิ่งนี้จะเริ่มขึ้นหลังจากผู้ฟังเฉพาะสำหรับการเลือกมิฉะนั้นค่าของ 'data-previous' จะถูกเขียนทับก่อนที่คุณจะสามารถอ่านได้

แน่นอนว่าคุณต้องการใช้ฟังแยกต่างหากสำหรับชุดก่อนหน้าและค่าตรวจสอบของคุณ มันเหมาะสมกับรูปแบบความรับผิดชอบเดียว

หมายเหตุ:นี่เป็นการเพิ่มฟังก์ชัน 'ก่อนหน้า' นี้ให้กับการเลือกทั้งหมดดังนั้นโปรดปรับตัวเลือกอย่างละเอียดหากจำเป็น


0

นี่คือการปรับปรุงคำตอบ @thisisboris มันเพิ่มมูลค่าปัจจุบันให้กับข้อมูลเพื่อให้รหัสสามารถควบคุมได้เมื่อมีการเปลี่ยนแปลงตัวแปรที่ตั้งเป็นค่าปัจจุบัน

(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

ทางออกที่ดีที่สุด:

$('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
คำตอบนี้ขึ้นอยู่กับไลบรารี "Selectric" js และไม่ใช่ใน 'ธรรมดา' jQuery หรือ javascript แม้ว่าจะดีที่สุด แต่ก็ไม่เหมาะกับคำถามดั้งเดิมหรือไม่บอกว่าผู้ใช้ต้องติดตั้งอย่างอื่นเพื่อให้ใช้งานได้
gadget00

0

มีหลายวิธีในการบรรลุผลตามที่คุณต้องการวิธีที่ต่ำต้อยของฉันในการทำเช่นนี้:

ปล่อยให้องค์ประกอบเก็บค่าไว้ก่อนหน้านี้ดังนั้นเพิ่มแอตทริบิวต์ 'previousValue'

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

เมื่อเริ่มต้นแล้ว 'previousValue' ตอนนี้สามารถใช้เป็นแอตทริบิวต์ ใน JS เพื่อเข้าถึงค่าก่อนหน้าของการเลือกนี้:

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

หลังจากเสร็จสิ้นการใช้ 'previousValue' ให้อัปเดตแอตทริบิวต์เป็นค่าปัจจุบัน


0

ฉันต้องการเปิดเผย div อื่นตามการเลือก

นี่คือวิธีที่คุณสามารถทำได้ด้วย jquery และ 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()
        }
    })
})
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.