jQuery Ereignis für ein <input> -Element ändern - eine Möglichkeit, den vorherigen Wert beizubehalten?

75

Ich habe heute Morgen gesucht und finde keine einfachen Lösungen ... im Grunde möchte ich eine Änderung in einem Eingabeelement erfassen, aber auch den vorherigen Wert kennen.

Hier ist ein Änderungsereignis und ein Eingabeelement in seiner einfachsten Form. Natürlich kann ich den neuen Wert mit $ (elem) .val () abrufen, aber gibt es eine hinterhältige Methode, die mir fehlt, um den vorherigen Wert abzurufen? Ich sehe in der jQuery-API nichts, um dies zu tun, aber vielleicht hat dies bereits jemand getan und hat einige Tipps?

<script>
    $(document).ready(function(){
        $('#myInputElement').bind('change', function(){
            //var oldvalue = ???
            var newvalue = $(this).val();
        });
    });
</script>
<input id="myInputElement" type="text">

Ich bin nicht dagegen, meine eigene Lösung zu schreiben, ich möchte nur sicherstellen, dass ich das Rad hier nicht neu erschaffe.

SeanW
quelle

Antworten:

104

Ein besserer Ansatz besteht darin, den alten Wert mit .data zu speichern. Dies erspart die Erstellung einer globalen Variable, von der Sie sich fernhalten sollten, und hält die Informationen im Element eingekapselt. Ein Beispiel aus der Praxis, warum Global Vars schlecht sind, ist hier dokumentiert

z.B

<script>
    //look no global needed:)

    $(document).ready(function(){
        // Get the initial value
       var $el = $('#myInputElement');
       $el.data('oldVal',  $el.val() );


       $el.change(function(){
            //store new value
            var $this = $(this);
            var newValue = $this.data('newVal', $this.val());
       })
       .focus(function(){
            // Get the value when input gains focus
            var oldValue = $(this).data('oldVal');
       });
    });
</script>
<input id="myInputElement" type="text">
rotes Quadrat
quelle
1
Ich lerne jeden Tag etwas Neues über jQuery ... dies ist das erste Mal, dass ich .data () gesehen habe, also werde ich heute definitiv mehr darüber lesen.
SeanW
1
@redsquare - total vergessen über .data () - schön!
Russ Cam
1
@redsquare: Ich wusste nichts über .data. Sehr schön :)
Daniel Moura
2
Nicht wahr, selbst MS rendern globale Variablen in ihren ms-Ajax-Skripten, die Personen auffangen können, wenn sie ihr Steuerelement zufällig so benennen wie die globale Variable. Def kein unerfahrenes einziges Problem
redsquare
5
@redsquare: Das ist großartig, aber es sieht so aus, als ob eine Logik nicht ganz richtig ist. .data('oldVal')wird immer nur gesetzt, wenn die Seite geladen wird und nie danach. Wahrscheinlich sollte es in changeoder focusfür so etwas sein $(this).data('oldVal', $(this).val())?
Alex Angas
16

Dies könnte den Trick tun:

$(document).ready(function() {
    $("input[type=text]").change(function() {
        $(this).data("old", $(this).data("new") || "");
        $(this).data("new", $(this).val());
        console.log($(this).data("old"));
        console.log($(this).data("new"));
    });
});

Demo hier

Salman A.
quelle
2
Ich mag diese Lösung, aber eines fehlt: Wenn der Wert durch einen anderen Javascript-Code geändert wird (wie in meinem Fall) oder wenn Sie den alten Wert zum ersten Mal benötigen, funktioniert dieser Code nicht. Sie müssen <input data-new="initialValue" />Ihren HTML- Code hinzufügen und diesen Wert bei jeder Manipulation überschreiben.
Александр Фишер
9
$('#element').on('change', function() {
    $(this).val($(this).prop("defaultValue"));
});
Hakadel
quelle
Der einfachste Weg, dies zu tun - sollte mehr Stimmen haben. Siehe: stackoverflow.com/questions/5244466/…
GreenieMeanie
Dies sollte zwar die akzeptierte Antwort sein: w3schools.com/jsref/prop_text_defaultvalue.asp
egdavid
2
Dies ist nach meinem Verständnis des vorherigen Wertes falsch . defaultValueist diejenige, die beim Laden der Seite festgelegt wurde. Der vorherige Wert (nach meinem Verständnis) ist der Wert des Steuerelements vor einer Änderung. Wenn der Standardwert 1 ist und der Benutzer 2 eingibt und ihn dann in 3 ändert, ist der vorherige Wert 2.
Salman A
4

Sie können den Wert des Eingabefelds in ein verstecktes Feld kopieren lassen, wenn der Fokus das Eingabefeld verlässt (was tun soll, was Sie wollen). Siehe Code unten:

<script>
    $(document).ready(function(){
        $('#myInputElement').bind('change', function(){
            var newvalue = $(this).val();
        });
        $('#myInputElement').blur(function(){
            $('#myHiddenInput').val($(this).val());
        });
    });
</script>
<input id="myInputElement" type="text">

(ungetestet, aber es sollte funktionieren).

brettkelly
quelle
Das ist keine schlechte Idee ... Ich muss testen. Ich frage mich, ob die Bindungs- und Unschärfeereignisse jedes Mal in derselben Reihenfolge ausgelöst werden. Wenn ja, funktioniert das möglicherweise. Alternativ kann ich möglicherweise das Fokusereignis verwenden, sodass ich den Wert speichere, wenn ein Element fokussiert ist. Bei Änderung habe ich dann die alten und neuen Werte ... Ich werde einige Tests durchführen und sehen, was ich mir einfallen lassen kann.
SeanW
Ich habe einige Tests durchgeführt und die Fokusmethode funktioniert hervorragend. Vielen Dank an euch beide für die Ideen / Beispiele!
SeanW
2

Jedes DOM-Element hat ein Attribut namens defaultValue. Sie können dies verwenden, um den Standardwert zu erhalten, wenn Sie nur die erste Änderung von Daten vergleichen möchten.

Joey Guerra
quelle
1

In Russ Antwort bindet er das Fokusereignis. Ich denke nicht, dass es notwendig ist.

Sie können den alten Wert im Änderungsereignis speichern.

<script>
    $(document).ready(function(){

        var newValue = $('#myInputElement').val();
        var oldValue;

        $('#myInputElement').change(function(){
            oldValue = newValue;
            newValue = $(this).val();
        });
    });
</script>
<input id="myInputElement" type="text">
Daniel Moura
quelle
Daniel, das Problem dabei ist, dass du den alten Wert nur einmal bekommst. Da mein Formular über einen Webservice (Ajax) gesendet wird, wird das Dokument nur einmal geladen, die Formularwerte können sich jedoch N-mal ändern. Durch die Verwendung der Fokusmethode kann ich garantiert den neuen Eingabewert erfassen.
SeanW
Oh, eigentlich - ich verstehe, was du tust ... mein Fehler. Ja, das würde auch funktionieren.
SeanW
1

Ein paar Punkte.

Verwenden Sie $ .data anstelle von $ .fn.data

// regular
$(elem).data(key,value);
// 10x faster
$.data(elem,key,value);

Dann können Sie den vorherigen Wert über das Ereignisobjekt abrufen, ohne Ihr Leben zu verkomplizieren:

    $('#myInputElement').change(function(event){
        var defaultValue = event.target.defaultValue;
        var newValue = event.target.value;
    });

Seien Sie gewarnt, dass defaultValue NICHT der zuletzt eingestellte Wert ist. Dies ist der Wert, mit dem das Feld initialisiert wurde. Sie können jedoch $ .data verwenden, um den "alten Wert" zu verfolgen.

Ich empfehle Ihnen, das "Ereignis" -Objekt in Ihren Ereignishandlerfunktionen immer zu deklarieren und sie mit einem Firebug (console.log (Ereignis)) oder etwas anderem zu überprüfen. Dort finden Sie viele nützliche Dinge, die Sie vor dem Erstellen / Zugreifen auf JQuery-Objekte bewahren (die großartig sind, aber wenn Sie schneller sein können ...)

monzonj
quelle
1

Ich habe diese Funktionen auf Vorschlag von Joey Guerra erstellt. Vielen Dank dafür. Ich arbeite ein bisschen daran, vielleicht kann es jemand benutzen. Die erste Funktion checkDefaults () wird aufgerufen, wenn sich eine Eingabe ändert, die zweite wird aufgerufen, wenn das Formular mit jQuery.post gesendet wird. div.updatesubmit ist meine Schaltfläche "Senden", und die Klasse "Bedarfsaktualisierung" ist ein Indikator dafür, dass eine Aktualisierung vorgenommen, aber noch nicht gesendet wurde.

function checkDefaults() {
    var changed = false;
        jQuery('input').each(function(){
            if(this.defaultValue != this.value) {
                changed = true;
            }
        });
        if(changed === true) {
            jQuery('div.updatesubmit').addClass("needsupdate");
        } else {
            jQuery('div.updatesubmit').removeClass("needsupdate");
        }
}

function renewDefaults() {
        jQuery('input').each(function(){
            this.defaultValue = this.value;
        });
        jQuery('div.updatesubmit').removeClass("needsupdate");
}
Maarten van Middelaar
quelle
0

Ich habe einen schmutzigen Trick gefunden, aber er funktioniert. Sie können die Hover-Funktion verwenden, um den Wert vor dem Ändern abzurufen.

Andrea Cammoranesi
quelle
1
Das würde nicht funktionieren, wenn der Benutzer die Tastatur verwendet, um zum Eingabefeld zu gelangen.
Beetstra
1
Was ist mit focus? das sollte sowohl Maus als auch Tastatur fangen
Steven Lu