Abrufen des Werts von select (Dropdown) vor dem Ändern


237

<select>Was ich erreichen möchte, ist, wann immer das Dropdown geändert wird, ich möchte den Wert des Dropdowns vor dem Ändern. Ich verwende die Version 1.3.2 von jQuery und das Ereignis on change, aber der Wert, den ich dort erhalte, ist nach der Änderung.

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

Nehmen wir an, die aktuelle Option My ist jetzt ausgewählt, wenn ich sie im Ereignis onchange in Stack ändere (dh wenn ich sie in Stack geändert habe). Ich möchte den vorherigen Wert, dh meinen erwarteten Wert in diesem Fall.

Wie kann dies erreicht werden?

Bearbeiten: In meinem Fall habe ich mehrere Auswahlfelder auf derselben Seite und möchte, dass auf alle dasselbe angewendet wird. Außerdem werden alle meine Auswahlen nach dem Laden der Seite über Ajax eingefügt.


1
Haben Sie dies überprüft: stackoverflow.com/questions/1983535/…
Rajat

Antworten:


434

Kombinieren Sie den Fokus - Ereignis mit dem Änderungsereignis zu erreichen , was Sie wollen:

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

Arbeitsbeispiel: http://jsfiddle.net/x5PKf/766


1
@Alpesh: Leider nicht, da Sie jQuery 1.4.1 oder höher nicht verwenden, können Sie live () nicht mit dem Fokus verwenden und Ereignisse ändern . Das einzige, was Sie tun können, ist, Ihr Skript so anzupassen, dass es nach dem Einfügen der Elemente in die Seite gebunden wird.
Andy E

1
Danke ich habe beide schon mit live verbunden und es hat erfolgreich funktioniert. :)
Alpesh

4
Beachten Sie, dass Sie sich auch auf das ausgewählte Element in Ihrem Änderungshandler konzentrieren sollten, da es sonst nach wiederholter Wertänderung nicht ausgelöst wird
Alex

52
Ich bin mit dieser Lösung nicht einverstanden. Wenn Sie den Wert einmal ändern, funktioniert es, aber wenn Sie es noch einmal tun, wird es nicht funktionieren. Sie müssen irgendwo klicken, um den Fokus zu verlieren, und erneut auf die Dropdown-Liste klicken. Ich schlage vor: $ ("# dropdownId"). On ('change', function () {var ddl = $ (this); var previous = ddl.data ('previous'); ddl.data ('previous', ddl .val ());});
free4ride

5
@ free4ride, um zu beheben, dass ich gerade $(this).blur();am Ende der Änderungsfunktion
aufrufe

135

Bitte verwenden Sie hierfür keine globale Variable. Speichern Sie den vorherigen Wert in den Daten. Dies ist ein Beispiel: http://jsbin.com/uqupu3/2/edit

der Code für 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());
  });
});

Ich habe gerade gesehen, dass Sie viele Auswahlen auf der Seite haben. Dieser Ansatz funktioniert auch für Sie, da Sie für jede Auswahl den vorherigen Wert in den Daten der Auswahl speichern


jQuery.data ist hier eine gute Lösung. Bei Ihrer Lösung erstellen Sie einen Abschluss für jede Auswahl, der sich perfekt auswirkt, wenn viele ausgewählte Elemente vorhanden sind
Avi Pinto

Mein Anliegen war nicht die Leistung, und ich bin nicht davon überzeugt, dass das Erstellen von Funktionen langsamer ist als jQuery.datasowieso.
August Lilleaas

9
Was ist Ihr Einwand gegen die Verwendung von jQuery.data? Soweit ich weiß, verwendet die jQuery-Bibliothek sie auch intern und empfiehlt die Verwendung
Avi Pinto

Stimmen Sie auf jeden Fall der Verwendung von jQuery-Daten zu - danke, dass Sie mich daran erinnert haben, dass ich die globale Variable verwenden wollte. Mit der globalen Variable ist nichts falsch, aber die Verwendung von Daten ist präziser. Aber es ist auch schön, den Fokus zu verketten und dann zu wechseln :)
Piotr Kula

4
@ppumkin: Eine Sache ist definitiv falsch mit einer globalen Variablen: Sie unterstützt nur eine select! Die akzeptierte Antwort wird unterbrochen, da sie mit allen übereinstimmt, selectaber nur den Wert der ersten speichert. data ist der bessere Weg, es zu tun. +1 :)
Gone Coding

86

Ich entscheide mich für die Lösung von Avi Pinto, die verwendet jquery.data()

Die Verwendung von Fokus ist keine gültige Lösung. Es funktioniert beim ersten Ändern der Optionen. Wenn Sie jedoch bei diesem Auswahlelement bleiben und die Taste "Auf" oder "Ab" drücken. Das Fokusereignis wird nicht erneut durchlaufen.

Die Lösung sollte also wie folgt aussehen:

//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
Tolle Lösung, viel besser als die ausgewählte Antwort!
TJL

2
Der zweite Teil funktioniert einwandfrei, aber der erste Teil legt das Datenattribut nicht fest. Irgendwelche Ideen?
Sinaesthetic

1
@Sinaesthetic, ich hatte das gleiche Problem (und habe diese Antwort bereits positiv bewertet). Ich glaube nicht, dass $ (this) die .data () -Methode überlebt. Die Antwort von Avi Pinto geht auf das ausgewählte Element für seinen Wert zurück, und dies hat bei mir funktioniert (also habe ich auch die von Avi positiv bewertet).
Goodeye

1
Dies wird seitdem nicht mehr funktionieren! == $ ('mySelect'). Hier ist eine feste Version. var $selectStatus = $('.my-select'); $selectStatus.on('change', function () { var newStatus = $(this).val(); var oldStatus = $(this).data('pre'); }).data('pre', $selectStatus.val());
Capy

2
@Sinaesthetic Diese Zeile setzt einen Wert für alle "mySelect" -Elemente. $('mySelect').data('pre', $(this).val());Es sollte lauten: $('mySelect').each(function() { $(this).data('pre', $(this).val()); });Ich habe nicht genug Ruf, um die Antwort zu bearbeiten: /
Abderrahim

8

Verfolgen Sie den Wert von Hand.

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

Ich kann den obigen Ansatz nicht verwenden, da ich mehrere Auswahlfelder auf derselben Seite habe, mit denen ich mich befassen muss.
Alpesh

1
Sie haben in Ihrer Frage nichts über mehrere Auswahlschaltflächen gesagt. Meine Antwort wurde aktualisiert, um mehrere Boxen zu unterstützen.
August Lilleaas

1
beste Antwort. Ich denke, diese Lösung ist besser als usign focus () und change (), weil sie für die Browserkompatibilität auf jquery angewiesen ist, dann auf den korrekten Ablauf der Ausführung beider Methoden
coorasse

@coorasse: Der korrekte Ablauf der Ausführung könnte niemals anders sein. Ein Wert für Auswahlfelder kann vom Benutzer niemals geändert werden, bevor das Element den Fokus erhält .
Andy E

Unter dem Gesichtspunkt der Verwendung von "Schließung" bin ich mir nicht sicher, ob dies besser ist als die "Fokus" -Lösung.
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());
});

Dies hat bei mir funktioniert, nur eine geringfügige Korrektur ist auf dem Dropdown-ID-Selektor aktiviert, anstatt auf einem, danke
malkoty

2
Änderungsereignis kann ohne Benutzerinteraktion auftreten, daher ist dies kein Kinderspiel
qdev

3

Ich verwende das Ereignis "live", meine Lösung ähnelt im Wesentlichen Dimitiar, aber anstatt "focus" zu verwenden, wird mein vorheriger Wert gespeichert, wenn "click" ausgelöst wird.

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

2
Ich würde das nicht benutzen. Was passiert, wenn der Benutzer das Auswahlelement mit einem Tabulator versehen und mit seinen Tastaturpfeilen eine andere Option auswählen kann?
Christian Lundahl

@Perplexor Ja, es funktioniert nicht mit Tasten, andernfalls werden alle Werte bei jedem Drücken der Taste gespeichert. Dies setzt nur voraus, dass der Benutzer auf das Dropdown-Menü klickt. Das Problem ist, dass "Live" -Ereignisse nicht mit "Fokus" funktionieren. Ich kenne keine bessere Lösung.
Cica Gustiani

Sie können den aktuellen Fokuswert in einer separaten Variablen speichern. Dies ist nur von oben, also bin ich mir nicht sicher, ob dies ideal ist.
Christian Lundahl

Wenn 'Fokus' mit 'Live'-Event funktionieren kann, ist es perfekt. Aber wenn Sie diese Dropdown-Menüs dynamisch erstellen, können Sie nur "live" verwenden, das weiß ich. Der 'Fokus' auf 'Live' löst leider nicht das Ereignis aus, um die neuen Werte zu speichern, aber ich weiß es nicht mit der neuen Abfrage
Cica Gustiani

live ist tot in den neuen Versionen von jQuery! [ stackoverflow.com/questions/14354040/…
Remo

2

Behalten Sie den aktuell ausgewählten Dropdown-Wert mit der ausgewählten Abfrage in einer globalen Variablen bei, bevor Sie die Dropdown-Aktionsfunktion "Bei Änderung" schreiben. Wenn Sie den vorherigen Wert in der Funktion festlegen möchten, können Sie die globale Variable verwenden.

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

Wie wäre es mit einem benutzerdefinierten jQuery-Ereignis mit einer eckigen Überwachungsschnittstelle?

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

Ich weiß, dass dies ein alter Thread ist, dachte aber, ich könnte ein kleines Extra hinzufügen. In meinem Fall wollte ich den Text, val und einige andere Daten attr weitergeben. In diesem Fall ist es besser, die gesamte Option als vorherigen Wert zu speichern, als nur den Wert.

Beispielcode unten:

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

BEARBEITEN:

Ich habe vergessen, .clone () zum Element hinzuzufügen. Wenn Sie dies nicht tun, wenn Sie versuchen, die Werte zurückzuziehen, ziehen Sie am Ende die neue Kopie der Auswahl und nicht die vorherige. Bei Verwendung der Methode clone () wird eine Kopie der Auswahl anstelle einer Instanz davon gespeichert.


0

Warum speichern Sie nicht den aktuell ausgewählten Wert, und wenn das ausgewählte Element geändert wird, wird der alte Wert gespeichert? (und Sie können es erneut aktualisieren, wie Sie möchten)


Nun, ich kann das nicht tun, weil ich in meinem Fall mehrere Auswahlfelder auf derselben Seite habe. Und das Speichern des Anfangswertes von allen am Anfang wird zu langwierig sein.
Alpesh

0

Verwenden Sie folgenden Code, ich habe es getestet und es funktioniert

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

Ich möchte eine weitere Option zur Lösung dieses Problems beitragen. da die oben vorgeschlagenen Lösungen mein Szenario nicht gelöst haben.

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

Dies verwendet jQuery, so dass def. ist hier eine Abhängigkeit, aber diese kann angepasst werden, um in reinem Javascript zu arbeiten. (Fügen Sie dem Body einen Listener hinzu, prüfen Sie, ob das ursprüngliche Ziel eine Auswahl war, führen Sie die Funktion aus, ...).

Wenn Sie den Änderungs-Listener an den Body anhängen, können Sie ziemlich sicher sein, dass dieser nach bestimmten Listenern für die Auswahl ausgelöst wird. Andernfalls wird der Wert von 'data-previous' überschrieben, bevor Sie ihn überhaupt lesen können.

Dies setzt natürlich voraus, dass Sie es vorziehen, separate Listener für Ihren Set-Prior- und Check-Wert zu verwenden. Es passt genau zum Muster der Einzelverantwortung.

Hinweis: Dadurch wird allen ausgewählten Optionen diese 'vorherige' Funktionalität hinzugefügt. Passen Sie daher die Selektoren bei Bedarf genau an.


0

Dies ist eine Verbesserung der Antwort von @thisisboris. Es fügt Daten einen aktuellen Wert hinzu, sodass der Code steuern kann, wann eine auf den aktuellen Wert festgelegte Variable geändert wird.

(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

Beste Lösung:

$('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
Diese Antwort basiert auf der js-Bibliothek "Selectric" und nicht auf "normalem" jQuery oder Javascript. Obwohl es das Beste ist, passt es weder zur ursprünglichen Frage noch sagt es, dass der Benutzer etwas anderes installieren muss, damit es funktioniert
gadget00

0

Es gibt verschiedene Möglichkeiten, um das gewünschte Ergebnis zu erzielen. Dies ist meine bescheidene Vorgehensweise:

Lassen Sie das Element seinen vorherigen Wert behalten, und fügen Sie ein Attribut 'previousValue' hinzu.

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

Nach der Initialisierung kann 'previousValue' jetzt als Attribut verwendet werden. Um in JS auf den vorherigen Wert dieser Option zuzugreifen, wählen Sie:

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

Nachdem Sie 'previousValue' verwendet haben, aktualisieren Sie das Attribut auf den aktuellen Wert.


0

Ich musste ein anderes Div basierend auf der Auswahl enthüllen

So können Sie es mit jquery und es6-Syntax machen

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()
        }
    })
})
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.