web-dev-qa-db-fra.com

Obtenir la valeur de select (liste déroulante) avant le changement

Ce que je veux réaliser, c’est que chaque fois que la liste déroulante <select> est modifiée, je souhaite connaître la valeur de la liste déroulante avant modification. J'utilise la version 1.3.2 de jquery et j'utilise l'événement on change, mais la valeur que j'obtiens là-bas est après le changement.

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

Disons que l'option actuelle My est sélectionnée maintenant lorsque je la modifie en pile dans l'événement onchange (c'est-à-dire lorsque je l'ai modifiée en pile). Je veux la valeur précédente, c'est-à-dire mon attendu dans ce cas.

Comment cela peut il etre accompli ?

Edit: Dans mon cas, je vais avoir plusieurs cases de sélection dans la même page et je veux que la même chose soit appliquée à tous. De plus, toutes mes sélections sont insérées après le chargement de la page via ajax.

205
Alpesh

Combinez l’événement focus avec l’événement change pour obtenir ce que vous voulez:

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

Exemple de travail: http://jsfiddle.net/x5PKf/766

394
Andy E

veuillez ne pas utiliser de variable globale pour cela - stockez la valeur précédente dans les données Voici un exemple: http://jsbin.com/uqupu3/2/edit

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

viens de voir que vous avez plusieurs sélections sur la page - cette approche fonctionnera également pour vous, car pour chaque sélection, vous enregistrerez la valeur précédente sur les données de la sélection.

126
Avi Pinto

Je choisis la solution Avi Pinto qui utilise jquery.data()

Utiliser le focus n'est pas une solution valable. Cela fonctionne la première fois que vous modifiez les options, mais si vous restez sur cet élément, appuyez sur la touche "haut" ou "bas". Cela ne passera plus par l'événement focus.

Donc, la solution devrait être plus ressemble à ce qui suit, 

//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
})
73
user1310312

Suivre la valeur à la main.

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;
  });
});
8
August Lilleaas
 $("#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());
});
6
free4ride

J'utilise l'événement "live", ma solution est fondamentalement similaire à celle de Dimitar, mais au lieu d'utiliser "focus", ma valeur précédente est enregistrée lorsque "click" est déclenché. 

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

Je sais que c'est un vieux fil, mais je pense pouvoir ajouter un petit extra. Dans mon cas, je voulais transmettre le texte, val et quelques autres données attr. Dans ce cas, il est préférable de stocker l’option entière en tant que valeur précédente plutôt que simplement en val.

Exemple de code ci-dessous:

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

MODIFIER:

J'ai oublié d'ajouter .clone () sur l'élément. en ne le faisant pas lorsque vous essayez d'extraire les valeurs, vous finissez par extraire la nouvelle copie de la sélection plutôt que la précédente. L'utilisation de la méthode clone () stocke une copie de la sélection au lieu d'une instance de celle-ci.

1
JBW

conservez la valeur déroulante actuellement sélectionnée avec la requête sélectionnée dans une variable globale avant d'écrire la fonction d'action de modification "à la modification" . Si vous souhaitez définir la valeur précédente dans la fonction, vous pouvez utiliser la variable globale.

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

Pourquoi ne pas utiliser un événement jQuery personnalisé avec une interface de type montre angulaire;

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

Pourquoi ne stockez-vous pas la valeur actuellement sélectionnée et lorsque l’élément sélectionné est modifié, l’ancienne valeur est stockée? (et vous pouvez le mettre à jour à nouveau si vous le souhaitez)

0
Soufiane Hassou
(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
Bilal

Utiliser le code suivant, je l'ai testé et son fonctionnement

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
Er.KT

Je voudrais contribuer une autre option pour résoudre ce problème; puisque les solutions proposées ci-dessus n'ont pas résolu mon scénario.

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

Ceci utilise jQuery pour que def. C'est une dépendance ici, mais cela peut être adapté pour fonctionner en JavaScript pur. (Ajoutez un écouteur au corps, vérifiez si la cible d'origine était une fonction select, execute, ...).

En attachant l'écouteur de modification au corps, vous pouvez être presque certain que cela déclenchera après des écouteurs spécifiques pour les sélections, sinon la valeur de 'data-previous' sera écrasée avant même de pouvoir la lire.

Ceci suppose bien sûr que vous préférez utiliser des écouteurs distincts pour votre set-previous et votre valeur de contrôle. Cela correspond parfaitement au modèle de responsabilité unique.

Remarque: Ceci ajoute cette fonctionnalité "précédente" à all selects, assurez-vous donc de régler les sélecteurs au besoin.

0
thisisboris

Il y a plusieurs façons d'obtenir le résultat souhaité, voici mon humble façon de le faire:

Laissez l'élément conserver sa valeur précédente, ajoutez donc un attribut 'previousValue'.

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

Une fois initialisé, 'previousValue' peut maintenant être utilisé comme attribut. En JS, pour accéder à la PreviousValue de cette sélection:

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

Une fois que vous avez terminé avec 'previousValue', mettez à jour l'attribut avec la valeur actuelle.

0
Rishi Alluri

Meilleure solution:

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

Ceci est une amélioration de la réponse de @thisisboris. Il ajoute une valeur actuelle aux données afin que le code puisse contrôler le moment où une variable définie sur la valeur actuelle est modifiée. 

(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
ermSO

Je devais révéler un div différent en fonction de la sélection

Voici comment procéder avec les syntaxes jquery et 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()
        }
    })
})
0
Dieter Gribnitz