更改前获取选择(下拉)的值


237

我要实现的事情是,无论何时<select>更改下拉列表,我都希望更改之前的下拉列表的值。我正在使用1.3.2版本的jQuery并使用on 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>

可以说,当我在onchange事件中将其更改为堆栈时(即,当我将其更改为堆栈时),现在选择了My选项,我希望它是先前的值,即在这种情况下的期望值。

如何做到这一点?

编辑:就我而言,我在同一页面上有多个选择框,并希望将相同的内容应用于所有选择框。通过页面加载通过ajax之后,也会插入所有我选择的内容。


1
你检查了这一点:stackoverflow.com/questions/1983535/...
拉雅

Answers:


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()focuschange事件一起使用。您唯一可以做的就是在将元素插入页面后调整脚本以进行绑定。
Andy E

1
谢谢,我已经绑定了直播功能并成功运行。:)
Alpesh

4
请注意,您还应该在更改处理程序中重点关注select元素,否则在重复更改值后不会触发它
Alex

52
我不同意这种解决方案。如果您更改该值一次,它将起作用,但是如果再更改一次,它将不起作用。您必须单击某个位置以松开焦点,然后再次单击下拉菜单。我建议:$(“#dropdownId”)。on('change',function(){var ddl = $(this); var previous = ddl.data('previous'); ddl.data('previous',ddl .val());});
free4ride 2014年

5
@ free4ride,要修复的问题是我只$(this).blur();在change函数的末尾调用
chiliNUT

135

请不要为此使用全局变量-将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 2010年

我关心的不是性能,我也不相信创建函数的速度要慢得多jQuery.data
8月Lilleaas 2010年

9
那么您对使用jQuery.data的反对是什么?据我所知,jQuery库也在内部使用它,并建议使用它
Avi Pinto 2010年

绝对同意使用jQuery Data-感谢您提醒我我将要使用全局变量。全局变量没什么问题,但是使用数据更简洁。但是链接重点然后进行更改也很好:)
Piotr Kula

4
@ppumkin:全局变量肯定有问题:它仅支持一个select!接受的答案将中断,因为它与所有匹配,select但仅存储第一个的值。data 更好的方法。+1 :)
Gone Coding

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
第二部分工作正常,但第一部分未设置data属性。有任何想法吗?
Sinaesthetic

1
@Sinaesthetic,我遇到了同样的问题(并且已经赞成了这个答案)。我认为$(this)无法在.data()方法中生存。Avi Pinto的答案可以回溯到select元素的值,这对我有用(因此我也赞成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 2014年

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
您没有对问题中的多个选择按钮说什么。更新了我的答案以支持多个框。
月8日Lilleaas

1
最佳答案。我认为此解决方案比使用usign focus()和change()更好,因为它依赖于jquery来提高浏览器兼容性,然后正确执行两种方法的流程
coorasse 2012年

@coorasse:正确的执行流程永远不会有任何不同。用户无法在元素获得焦点之前更改选择框的值。话虽这么说,这种方法也没有错:-)
Andy 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());
});

这对我
有用

2
更改事件可以在没有用户交互的情况下发生,所以这不是明智的
做法

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 2015年

@Perplexor是的,它不能与键一起使用,否则每次按下键时它将存储每个值。这仅假设用户单击下拉菜单。问题是“直播”事件无法与“焦点”配合使用,我不知道有什么更好的解决方案。
Cica Gustiani 2015年

您可以将当前的焦点值存储到单独的变量中。这只是从我的头上来的,所以我不确定这是否理想。
克里斯蒂安·隆达

如果“焦点”可以与“现场”活动配合使用,那就太完美了。但是,如果您动态创建这些下拉菜单,则只能使用“实时”,这就是我所知道的。不幸的是,对“实时”的“关注”不会触发事件来存储新值,但我不知道新的jQuery
Cica Gustiani

live在新版jQuery中已死![ stackoverflow.com/questions/14354040/…–
雷莫

2

在编写下拉的“ on change”动作函数之前,将当前选定的下拉列表值和选定的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

我知道这是一个旧线程,但我想我可能会添加一些额外的内容。就我而言,我想传递文本,val和其他一些数据属性。在这种情况下,最好将整个选项存储为prev值而不是val。

下面的示例代码:

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()方法存储select的副本,而不是其实例。


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,以便def。在这里是一个依赖项,但这可以调整为在纯JavaScript中工作。(向主体添加一个侦听器,检查原始目标是否为select,execute函数,...)。

通过将更改侦听器附加到主体,您几乎可以确保它会在选择的特定侦听器之后触发,否则,“ data-previous”的值将被覆盖,甚至无法读取。

当然,这是假设您希望为set-previous和check-value使用单独的侦听器。它恰好适合单一责任模式。

注意:这会将“以前的”功能添加到所有选择中,因此请确保在需要时微调选择器。


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。尽管是最好的方法,但它既不适合最初的问题,也
未说明

0

有几种方法可以达到您想要的结果,这是我谦虚的方法:

让元素保留其先前的值,因此添加一个属性“ previousValue”。

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

初始化后,“ previousValue”现在可以用作属性。在JS中,要访问此内容的previousValue,请选择:

$("#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()
        }
    })
})
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.