【问题标题】:Getting value of select (dropdown) before change在更改之前获取选择(下拉)的值
【发布时间】:2011-05-03 20:52:15
【问题描述】:

我想要实现的是每当<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 加载页面后插入的。

【问题讨论】:

标签: javascript jquery jquery-events


【解决方案1】:

focus 事件与 change 事件结合起来,达到你想要的效果:

(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

【讨论】:

  • @Alpesh:很遗憾,因为您没有使用 jQuery 1.4.1 或更高版本,所以您无法将 live()focus 和 change 事件。您唯一能做的就是在将元素插入页面后调整脚本以进行绑定。
  • 谢谢,我已经与 live 绑定了,并且成功运行。 :)
  • 注意,在你的change handler中你也应该关注select元素,否则重复值改变后不会触发
  • 我不同意这个解决方案。如果您更改该值一次,它将起作用,但如果您再更改一次,则不会。您必须单击某处以松开焦点,然后再次单击下拉菜单。我建议: $("#dropdownId").on('change', function () { var ddl = $(this); var previous = ddl.data('previous'); ddl.data('previous', ddl .val()); });
  • @free4ride,为了解决这个问题,我只是在更改函数结束时调用$(this).blur();
【解决方案2】:

请不要为此使用全局变量 - 将 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 是一个很好的解决方案。在您的解决方案中,您正在为每个选择创建一个闭包,如果有很多选择元素,则会产生性能影响
  • 我关心的不是性能,而且我不相信创建函数会比jQuery.data 慢。
  • 那么您反对使用 jQuery.data 的原因是什么?据我所知,jQuery 库也在内部使用它,并建议使用它
  • 绝对同意使用 jQuery Data - 感谢提醒我我即将使用全局变量。全局变量没有问题,但使用数据更简洁。但是链接焦点然后改变也很好:)
  • @ppumkin:一个全局变量肯定有问题:它只支持一个select!接受的答案将中断,因为它匹配所有 select 但仅存储第一个的值。 data 更好的方法。 +1 :)
【解决方案3】:

我选择使用 jquery.data() 的 Avi Pinto 解决方案

使用焦点不是有效的解决方案。它在您第一次更改选项时起作用,但如果您停留在该选择元素上,然后按“向上”或“向下”键。它不会再次通过焦点事件。

所以解决方案应该更像下面这样,

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

【讨论】:

  • 很好的解决方案,比选择的答案好得多!
  • 第二部分工作正常,但第一部分没有设置数据属性。有什么想法吗?
  • @Sinaesthetic,我遇到了同样的问题(并且已经赞成这个答案)。我认为 $(this) 无法在 .data() 方法中幸存下来。 Avi Pinto 的答案可以追溯到 select 元素的值,这对我有用(所以我也赞成 Avi)。
  • 这将不起作用,因为这个!== $('mySelect')。这是一个固定版本。 var $selectStatus = $('.my-select'); $selectStatus.on('change', function () { var newStatus = $(this).val(); var oldStatus = $(this).data('pre'); }).data('pre', $selectStatus.val());
  • @Sinaesthetic 这一行为所有“mySelect”元素设置了一个值$('mySelect').data('pre', $(this).val()); 它应该是:$('mySelect').each(function() { $(this).data('pre', $(this).val()); }); 我没有足够的声誉来编辑答案:/
【解决方案4】:

手动跟踪值。

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

【讨论】:

  • 我不能使用上述方法,因为我在同一个页面中有多个选择框,我必须与之打交道。
  • 您对问题中的多个选择按钮只字未提。更新了我的答案以支持多个框。
  • 最佳答案。我认为这个解决方案比 usign focus() 和 change() 更好,因为它依赖 jquery 来实现浏览器兼容性,而不是两种方法的正确执行流程
  • @coorasse:正确的执行流程永远不会有任何不同。用户元素获得焦点之前永远不能更改选择框的值。话虽如此,这种方法也没有错:-)
  • 从“关闭”使用的角度来看,我不确定这是否比“焦点”解决方案更好。
【解决方案5】:
 $("#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());
});

【讨论】:

  • 这对我有用,只是对 dropdownId 选择器进行了轻微的更正,而不是一个,谢谢
  • 更改事件可以在没有用户交互的情况下发生,所以这不是一个脑筋急转弯
【解决方案6】:

我正在使用事件“live”,我的解决方案基本上与 Dimitiar 类似,但不是使用“focus”,而是在触发“click”时存储我之前的值。

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

【讨论】:

  • 我不会用这个。如果用户“选项卡”进入选择元素并使用他的键盘箭头选择不同的选项怎么办?
  • @Perplexor 是的,它不适用于键,否则每次按下键时它都会存储每个值。这仅假设用户单击下拉菜单。问题是“现场”活动不适用于“焦点”,我不知道有什么更好的解决方案。
  • 您可以将焦点上的当前值存储到一个单独的变量中。这只是我的想法,所以我不确定这是否理想。
  • 如果 'focus' 可以与 'live' 活动一起使用,那将是完美的。但是如果你动态地创建那些下拉菜单,你只能使用'live',这就是我所知道的。不幸的是,“live”上的“focus”不会触发存储新值的事件,但我不知道新的 jquery
  • live 在新版本的 jQuery 中已经死了! [stackoverflow.com/questions/14354040/…
【解决方案7】:

在编写下拉“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;
         }
  });
});

【讨论】:

    【解决方案8】:

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

    让元素保持之前的值,所以添加一个属性'previousValue'。

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

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

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

    使用完“previousValue”后,将属性更新为当前值。

    【讨论】:

      【解决方案9】:

      如何使用带有角度手表类型界面的自定义 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
      });
      

      【讨论】:

        【解决方案10】:

        我知道这是一个旧线程,但我想我可以补充一点。就我而言,我想传递文本、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()。当您尝试拉回值时不这样做,您最终会拉入 select 的新副本而不是以前的副本。使用 clone() 方法存储选择的副本而不是它的实例。

        【讨论】:

        • 嗨,我尝试了您的解决方案,并且在我第一次更改下拉值时一切正常。但是,以前的值永远不会重置,所以我一直得到相同的以前的值和文本结果。
        【解决方案11】:

        嗯,为什么不存储当前所选值,并且当更改所选项目时,您将存储存储的旧值? (您可以根据需要再次更新)

        【讨论】:

        • 好吧,我不能这样做,因为在我的情况下,我在同一页面中有多个选择框。而且一开始就保存all的初始值太麻烦了。
        【解决方案12】:

        使用下面的代码,我已经测试过它和它的工作原理

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

        【讨论】:

          【解决方案13】:
          (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();
          })();
          

          【讨论】:

            【解决方案14】:

            我想提供另一个选项来解决这个问题;因为上面提出的解决方案没有解决我的情况。

            (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 中工作。 (在主体中添加一个监听器,检查原始目标是否是一个选择、执行函数……)。

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

            这当然是假设您更喜欢为您的 set-previous 和 check-value 使用单独的侦听器。它非常适合单一职责模式。

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

            【讨论】:

              【解决方案15】:

              这是对@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() );
                      }
                  );
              })();
              

              【讨论】:

                【解决方案16】:

                最佳解决方案:

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

                【讨论】:

                • 此答案基于“Selectric”js 库,而不是“普通”jQuery 或 javascript。尽管是最好的,但它不适合最初的问题,也没有说用户需要安装其他东西才能工作
                【解决方案17】:

                我需要根据选择显示不同的 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()
                        }
                    })
                })
                

                【讨论】:

                  【解决方案18】:

                  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>

                  【讨论】:

                  • 您不应仅发布代码答案。请考虑编辑问题以包含有关解决方案的描述。这为用户提供了更多好处。
                  【解决方案19】:

                  这是一个简单的解决方案,没有包含 jQuery、DOM 遍历、事件绑定、全局变量等的开销。它通过包含“之前”和“之后”值的消息提示用户确认更改,并取消或根据他们的选择接受更改。

                  <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 在这里: https://jsfiddle.net/humbads/f3a0v8ys/

                  注意 1:onchange 处理程序的编写方式是这样的,因此该解决方案也可以与具有 AutoPostBack=True 和 OnSelectedIndexChanged 处理程序的 ASP.Net DropDownList 控件一起使用。

                  注意 2:选项不应包含空白值。如果是,请更改初始值。

                  【讨论】:

                    【解决方案20】:

                    将其存储在自属性中(准备好文档):

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

                    然后与更改后的值进行比较:

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

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多