Getting value of select (dropdown) before change

JavascriptJqueryJquery Events

Javascript Problem Overview


The thing I want to achieve is whenever the <select> dropdown is changed I want the value of the dropdown before change. I am using 1.3.2 version of jQuery and using on change event but the value I am getting over there is after change.

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

Lets say currently option My is selected now when I change it to stack in the onchange event (i.e. when I changed it to stack) I want it's previous value i.e. my expected in this case.

How can this be achieved?

Edit: In my case I am having multiple select boxes in the same page and want same thing to be applied to all of them. Also all of my select are inserted after page load through ajax.

Javascript Solutions


Solution 1 - Javascript

Combine the focus event with the change event to achieve what you want:

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

Working example: http://jsfiddle.net/x5PKf/766

Solution 2 - Javascript

please don't use a global var for this - store the prev value at the data here is an example: http://jsbin.com/uqupu3/2/edit

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

just saw that you have many selects on page - this approach will also work for you since for each select you will store the prev value on the data of the select

Solution 3 - Javascript

I go for Avi Pinto's solution which uses jquery.data()

Using focus isn't a valid solution. It works at first time you change the options, but if you stay on that select element, and press key "up" or "down". It won't go through the focus event again.

So the solution should be more looks like the following,

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

Solution 4 - Javascript

Track the value by 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;
  });
});

Solution 5 - Javascript

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

Solution 6 - Javascript

I am using event "live", my solution is basically similiar with Dimitiar, but instead of using "focus", my previous value is stored when "click" is triggered.

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

Solution 7 - Javascript

keep the currently selected drop down value with chosen jquery in a global variable before writing the drop down 'on change' action function. If you want to set previous value in the function you can use the global variable.

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

Solution 8 - Javascript

There are several ways to achieve your desired result, this my humble way of doing it:

Let the element hold its previous value, so add an attribute 'previousValue'.

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

Once initialized, 'previousValue' could now be used as an attribute. In JS, to access the previousValue of this select:

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

After you are done using 'previousValue', update the attribute to current value.

Solution 9 - Javascript

How about using a custom jQuery event with an angular watch type interface;

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

Solution 10 - Javascript

I know this is an old thread, but thought I may add on a little extra. In my case I was wanting to pass on the text, val and some other data attr. In this case its better to store the whole option as a prev value rather than just the val.

Example code below:

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

EDIT:

I forgot to add .clone() onto the element. in not doing so when you try to pull back the values you end up pulling in the new copy of the select rather than the previous. Using the clone() method stores a copy of the select instead of an instance of it.

Solution 11 - Javascript

Well, why don't you store the current selected value, and when the selected item is changed you will have the old value stored? (and you can update it again as you wish)

Solution 12 - Javascript

Use following code,I have tested it and its working

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

Solution 13 - Javascript

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

Solution 14 - Javascript

I'd like to contribute another option to solve this issue; since the solutions proposed above did not solve my scenario.

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

This does use jQuery so that def. is a dependency here, but this can be adapted to work in pure javascript. (Add a listener to the body, check if the original target was a select, execute function, ...).

By attaching the change listener to the body, you can pretty much be sure this will fire after specific listeners for the selects, otherwise the value of 'data-previous' will be overwritten before you can even read it.

This is of course assuming that you prefer to use separate listeners for your set-previous and check-value. It fits right in with the single-responsibility pattern.

Note: This adds this 'previous' functionality to all selects, so be sure to fine-tune the selectors if needed.

Solution 15 - Javascript

This is an improvement on @thisisboris answer. It adds a current value to data, so the code can control when a variable set to the current value is changed.

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

Solution 16 - Javascript

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

Solution 17 - Javascript

I needed to reveal a different div based on the selection

This is how you can do it with jquery and es6 syntax

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

Solution 18 - Javascript

var last_value;
var current_value;
$(document).on("click","select",function(){
	last_value = $(this).val();
}).on("change","select",function(){
	current_value = $(this).val();

	console.log('last value - '+last_value);
	console.log('current value - '+current_value);
});

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select name="test">
<option value="stack">Stack</option>
<option value="overflow">Overflow</option>
<option value="my">My</option>
<option value="question">Question</option>
</select>

Solution 19 - Javascript

Here is a simple solution without the overhead of including jQuery, DOM traversal, event binding, global variables, etc. It prompts the user to confirm the change with a message containing the 'before' and 'after' value, and cancels or accepts the change depending on their choice.

<select name="test" 
  onfocus="handleOnFocus(this);" 
  onchange="if(handleOnChange(this) == false) { return false; }"
  data-original-selected-index="">
<option value="stack">Stack</option>
<option value="overflow">Overflow</option>
<option value="my">My</option>
<option value="question">Question</option>
</select>


// Prompt user to confirm the change
function handleOnChange(selectObj) {
  var confirmationMessage = 'Change ' +
    selectObj.options[selectObj.dataset.originalSelectedIndex].text + 
    ' to ' + 
    selectObj.options[selectObj.selectedIndex].text + '?';

  if (!confirm(confirmationMessage)) {
    selectObj.selectedIndex = selectObj.dataset.originalSelectedIndex;
    return false;
  } else {
    selectObj.dataset.originalSelectedIndex = selectObj.selectedIndex;
    return true;
  }
}

// Initialize original selected index (one-time)
function handleOnFocus(selectObj) {
  if (selectObj.dataset.originalSelectedIndex == '') {
    selectObj.dataset.originalSelectedIndex = selectObj.selectedIndex;
  }
}

JSFiddle is here: https://jsfiddle.net/humbads/f3a0v8ys/

Note 1: The onchange handler is written the way it is so that this solution can also work with ASP.Net DropDownList controls with AutoPostBack=True and an OnSelectedIndexChanged handler.

Note 2: The options should not contain a blank value. If they do, change the initial value.

Solution 20 - Javascript

Store it in a self-attribute (on document ready):

$('#myselect').attr('orig',$('#myselect').val());

and then compare with the changed value:

if ($('#myselect').attr('orig')!=$('#myselect').val()) ...

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlpeshView Question on Stackoverflow
Solution 1 - JavascriptAndy EView Answer on Stackoverflow
Solution 2 - JavascriptAvi PintoView Answer on Stackoverflow
Solution 3 - Javascriptuser1310312View Answer on Stackoverflow
Solution 4 - JavascriptAugust LilleaasView Answer on Stackoverflow
Solution 5 - Javascriptfree4rideView Answer on Stackoverflow
Solution 6 - JavascriptCica GustianiView Answer on Stackoverflow
Solution 7 - JavascriptDeshani TharakaView Answer on Stackoverflow
Solution 8 - JavascriptRishi AlluriView Answer on Stackoverflow
Solution 9 - JavascriptNick MView Answer on Stackoverflow
Solution 10 - JavascriptJBWView Answer on Stackoverflow
Solution 11 - JavascriptSoufiane HassouView Answer on Stackoverflow
Solution 12 - JavascriptEr.KTView Answer on Stackoverflow
Solution 13 - JavascriptBilalView Answer on Stackoverflow
Solution 14 - JavascriptthisisborisView Answer on Stackoverflow
Solution 15 - JavascriptermSOView Answer on Stackoverflow
Solution 16 - JavascriptViESView Answer on Stackoverflow
Solution 17 - JavascriptDieter GribnitzView Answer on Stackoverflow
Solution 18 - JavascriptGajanan ChitareView Answer on Stackoverflow
Solution 19 - JavascripthumbadsView Answer on Stackoverflow
Solution 20 - JavascriptArvyView Answer on Stackoverflow