Получение значения select (выпадающего) до изменения

237

Я хочу добиться того, чтобы при каждом изменении <select>раскрывающегося списка я хотел, чтобы значение раскрывающегося списка было изменено. Я использую 1.3.2 версию jQuery и использую событие 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>

Допустим, в настоящее время опция My выбрана сейчас, когда я изменяю ее на стек в событии onchange (то есть, когда я меняю ее на стек), я хочу, чтобы это было предыдущее значение, т.е. мое ожидание в этом случае.

Как этого достичь?

Изменить: в моем случае у меня есть несколько полей выбора на одной странице и хочу, чтобы ко всем из них применялась одна и та же вещь. Также все мои выбранные вставляются после загрузки страницы через ajax.

Alpesh
источник
1
Вы проверили это: stackoverflow.com/questions/1983535/…
Раджат

Ответы:

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 () с событиями focus и change . Единственное, что вы можете сделать, это настроить скрипт для привязки после вставки элементов на страницу.
Энди Е
1
Спасибо, я уже связал оба с живой, и это сработало успешно. :)
Alpesh
4
Обратите внимание, что вы должны также выделить элемент select в вашем обработчике изменений, иначе он не будет запущен после повторного изменения значения
Alex
52
Я не согласен с этим решением. Если вы измените значение один раз, оно будет работать, но если вы сделаете это еще раз, это не сработает. Вы должны щелкнуть где-нибудь, чтобы потерять фокус, и еще раз щелкнуть на раскрывающемся списке Я предлагаю: $ ("# dropdownId"). On ('change', function () {var ddl = $ (this); var previous = ddl.data ('previous'); ddl.data ('previous', ddl .val ());});
free4ride
5
@ free4ride, чтобы исправить это, я просто вызываю $(this).blur();в конце функции изменения
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());
  });
});

только что увидел, что у вас есть много выборок на странице - этот подход также будет работать для вас, так как для каждого выбора вы будете сохранять предыдущее значение в данных выбора

Ави Пинто
источник
jQuery.data является хорошим решением здесь. в вашем решении вы создаете замыкание для каждого выбора, который имеет эффект перфекта, если есть много элементов выбора
Avi Pinto
Я беспокоился не о производительности, и я не уверен, что создание функций медленнее, чем в jQuery.dataлюбом случае.
Август Лиллеас
9
Итак, что вы возражаете против использования jQuery.data? Насколько я знаю, библиотека jQuery также использует ее для внутренних целей и рекомендует ее использовать
Avi Pinto
Определенно согласен с использованием jQuery Data. Спасибо, что напомнили, что я собирался использовать глобальную переменную. Ничего плохого в глобальной переменной нет, но использование данных более лаконично. Но сковывать фокус, а потом менять тоже приятно :)
Петр Кула
4
@ppumkin: Одна вещь определенно не так с глобальной переменной: она поддерживает только одну select! Принятый ответ будет нарушен, так как он соответствует всем, selectно сохраняет только значение первого. data это лучший способ сделать это. +1 :)
Ушел кодирование
86

Я иду на решение Ави Пинто, которое использует 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
})
user1310312
источник
3
Отличное решение, намного лучше, чем выбранный ответ!
TJL
2
Вторая часть работает нормально, но первая часть не устанавливает атрибут данных. Любые идеи?
Синастетическая
1
@Sinaesthetic, у меня была та же проблема (и уже проголосовал за этот ответ). Я не думаю, что $ (this) переживет метод .data (). Ответ Ави Пинто восходит к элементу select по его значению, и это сработало для меня (поэтому я также проголосовал против Ави).
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
2
@Sinaesthetic - эта строка устанавливает одно значение для всех элементов «mySelect». $('mySelect').data('pre', $(this).val());Это должно быть так: $('mySelect').each(function() { $(this).data('pre', $(this).val()); });У меня недостаточно репутации, чтобы редактировать ответ: /
Абдеррахим
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
Вы ничего не сказали о множественных кнопках выбора в вашем вопросе. Обновил мой ответ для поддержки нескольких ящиков.
Август Лиллеас
1
лучший ответ. Я думаю, что это решение лучше, чем usign focus () и change (), потому что оно опирается на jquery для совместимости с браузерами, а не на правильный поток выполнения обоих методов
coorasse
@coorasse: правильный ход выполнения никогда не может быть другим. Значение блоков выбора никогда не может быть изменено пользователем, пока элемент не сфокусируется. При этом, в этом подходе нет ничего плохого :-)
Энди Э,
С точки зрения использования 'замыкания', я не уверен, что это лучше, чем решение 'focus'.
Джеймс Полус
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());
});
free4ride
источник
Это сработало для меня только небольшая коррекция на селектор dropdownId
включен
2
Событие изменения может произойти без взаимодействия с пользователем, так что это не просто
qdev
3

Я использую событие «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 
    });
Кика Густиани
источник
2
Я бы не использовал это. Что если пользователь «вкладывает» элемент select и использует стрелки клавиатуры для выбора другого параметра?
Кристиан Лундаль
@Perplexor да, он не будет работать с клавишами, иначе он будет хранить каждое значение при каждом нажатии клавиши. Это только предполагает, что пользователь щелкает раскрывающееся меню. Проблема в том, что «живое» событие не работает с «фокусом», лучшего решения я не знаю.
Кика Густиани
Вы можете сохранить текущее значение в фокусе в отдельной переменной. Это только из головы, поэтому я не уверен, что это идеально.
Кристиан Лундаль
Если «фокус» может работать с «живым» событием, это будет прекрасно. Но если вы динамически создаете эти выпадающие меню, вы можете использовать только «живой», это то, что я знаю. «Фокус» на «живой», к сожалению, не запускает событие для сохранения новых значений, но я не знаю с новым jquery
Cica Gustiani
Live мертв в новых версиях jQuery! [ stackoverflow.com/questions/14354040/…
Remo
2

сохраните текущее выбранное выпадающее значение с выбранным 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 и некоторые другие данные. В этом случае лучше хранить весь параметр как предыдущее значение, а не только значение 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 () сохраняет копию выбора вместо его экземпляра.

JBW
источник
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;
            }
});
Er.KT
источник
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. (Добавьте слушателя к телу, проверьте, была ли исходная цель выбором, выполнить функцию, ...).

Прикрепив прослушиватель изменений к телу, вы можете быть уверены, что он сработает после определенных прослушивателей для выбора, в противном случае значение «data-previous» будет перезаписано до того, как вы сможете его прочитать.

Это, конечно, предполагает, что вы предпочитаете использовать отдельных слушателей для вашего set-previous и check-value. Это вписывается в шаблон с единой ответственностью.

Примечание. Это добавляет эту «предыдущую» функциональность ко всем выборам, поэтому при необходимости обязательно настройте их.

thisisboris
источник
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() );
        }
    );
})();
ermSO
источник
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);
});
Vies
источник
1
этот ответ основан на js-библиотеке «Selectric», а не на «обычном» jQuery или javascript. Даже если это лучшее, оно не подходит для первоначального вопроса и не говорит, что пользователю нужно установить что-то еще, чтобы оно работало
gadget00
0

Есть несколько способов достичь желаемого результата, это мой скромный способ сделать это:

Пусть элемент содержит свое предыдущее значение, поэтому добавьте атрибут «previousValue».

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

После инициализации «previousValue» теперь можно использовать в качестве атрибута. В JS для доступа к предыдущему значению этого выберите:

$("#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()
        }
    })
})
Дитер Грибниц
источник