Отримання значення вибору (випадаючого) перед зміною


237

Те, що я хочу досягти - це щоразу, коли <select>спадне меню змінюється, я хочу значення спаду перед зміною. Я використовую версію jQuery 1.3.2 і використовую події зміни, але значення, яке я отримую там, є після зміни.

<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 (тобто коли я змінив його на stack), я хочу, щоб це було попереднє значення, тобто моє очікуване в цьому випадку.

Як цього можна досягти?

Редагувати: У моєму випадку я маю кілька полів вибору на одній сторінці і хочу, щоб те саме було застосовано до всіх. Крім того, всі мої виділення вставляються після завантаження сторінки через ajax.


1
Ви перевірили це: stackoverflow.com/questions/1983535/…
Rajat

Відповіді:


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 () з фокусом та зміною подій. Єдине, що ви могли зробити, - це налаштувати ваш сценарій для прив’язки після вставки елементів на сторінку.
Енді Е

1
Дякую, я вже пов'язував обидва з живими, і це працювало успішно. :)
Альпеш

4
Зауважте, що вам слід також виділити елемент вибору у вашому обробці змін, інакше він не буде спрацьовувати після повторної зміни значення
Alex

52
Я не згоден з цим рішенням. Якщо ви зміните значення одного разу, воно буде працювати, але якщо ви зробите це ще раз, воно не стане. Ви повинні натиснути кудись, щоб втратити фокус, а інший натиснути спадне меню. Я пропоную: $ ("# dropdownId"). On ('змінити', функцію () {var ddl = $ (це); var previous = ddl.data ('попередній'); ddl.data ('попередній', ddl .val ());});
free4ride

5
@ free4ride, щоб виправити, що я просто дзвоню $(this).blur();в кінці функції зміни
chiliNUT

135

будь ласка, не використовуйте для цього глобальний var - збережіть попереднє значення у даних, ось ось приклад: 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- дякую, що нагадали мені, що я збирався використовувати глобальний var .. Нічого не так у глобальному var, але використання даних є більш стислим. Але прикувати фокус, а потім зміни також приємно :)
Пьотр Кула

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

3
Чудове рішення, набагато краще, ніж обрана відповідь!
TJL

2
Друга частина працює добре, але перша частина не встановлює атрибут даних. Будь-які ідеї?
Сінестетик

1
@Sinaesthetic, у мене було те саме питання (і я вже схвалив цю відповідь). Я не думаю, що $ (це) переживає метод .data (). Відповідь Аві Пінто повертається до елементу вибору за його значенням, і це спрацювало для мене (тому я також підтримав Аві).
goodeye

1
Це не працює, оскільки це! == $ ('mySelect'). Ось фіксована версія. var $selectStatus = $('.my-select'); $selectStatus.on('change', function () { var newStatus = $(this).val(); var oldStatus = $(this).data('pre'); }).data('pre', $selectStatus.val());
Кейп

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

Я не можу використовувати вищезазначений підхід, оскільки у мене на тій же сторінці є декілька вікон, з якими я маю справу.
Альпеш

1
Ви нічого не сказали про кілька кнопок вибору у своєму запитанні. Хоча я оновив свою відповідь на підтримку декількох коробок.
Серпень Ліллеас

1
найкраща відповідь. Я думаю, що це рішення краще, ніж usign focus () та change (), тому що воно покладається на jquery для сумісності веб-переглядачів, то правильне виконання ef обох методів
coorasse

@coorasse: правильний потік виконання ніколи не може бути різним. Значення полів вибору ніколи не може бути змінене користувачем, перш ніж елемент займе фокус. Якщо говорити, у цьому підході немає нічого поганого :-)
Енді Е

З точки зору використання «закриття», я не впевнений, чи краще це рішення, ніж «фокус».
Джеймс Поулоз

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

Це працювало для мене, лише невелика корекція - це на селекторі
dropdownId

2
Подія зміни може відбуватися без взаємодії з користувачем, так що це не
мозковий оператор

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
Я б не користувався цим. Що робити, якщо користувач "вкладе" елемент вибору та використовує стрілки клавіатури, щоб вибрати інший варіант?
Крістіан Лундал

@Perplexor так, він не працюватиме з клавішами, інакше він буде зберігати кожне значення кожного разу при натисканні клавіші. Це лише припущення, що користувач натисне спадне меню. Проблема в тому, що подія "наживо" не працюватиме з "фокусом", я не знаю кращого рішення.
Cica Gustiani

Ви можете зберігати поточне значення на фокусі в окрему змінну. Це просто з моєї голови, тому я не впевнений, чи ідеально це.
Крістіан Лундаль

Якщо "фокус" може працювати з подією "наживо", це буде ідеально. Але якщо ви динамічно створюєте ці спадні меню, ви можете використовувати лише "живе", це я знаю. На жаль, "фокус" на "живому" не викликає події для зберігання нових цінностей, на жаль, але я не знаю, як новий jquery
Cica Gustiani

у нових версіях jQuery live мертвий! [ stackoverflow.com/questions/14354040/…
видалити

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

Я знаю, що це стара тема, але подумав, що я можу додати ще трохи. У моєму випадку я хотів передати текст, вал та деякі інші дані attr. У цьому випадку краще зберігати весь варіант як попереднє значення, а не лише значення 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 (), зберігає копію вибраного, а не його екземпляра.


0

Ну чому б вам не зберегти поточне вибране значення, і коли вибраний елемент буде змінено, ви збережете старе значення? (і ви можете оновити його знову за бажанням)


Ну, я не можу цього зробити, тому що в моєму випадку у мене на тій же самій сторінці є декілька вікон. І збереження початкової вартості всіх на початку буде занадто клопітким.
Альпеш

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, ...).

Приєднавши слухач змін до тіла, ви можете бути впевнені, що це буде спрацьовувати після того, як конкретні слухачі будуть обрані для вибраних, інакше значення "попередні дані" буде замінено перед тим, як ви навіть зможете його прочитати.

Звичайно, це передбачає, що ви віддаєте перевагу використовувати окремі слухачі для попереднього встановленого та контрольного значення. Це добре вписується в модель єдиної відповідальності.

Примітка. Це додає цю "попередню" функціональність усім вибору, тому обов'язково допрацюйте селектори, якщо потрібно.


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
ця відповідь заснована на бібліотеці js "Selectric", а не на "звичайному" jQuery або javascript. Eventhough найкраще, він не відповідає оригінальному питанню, а також не говорить про те, що користувачеві потрібно встановити щось інше, щоб він працював
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

Мені потрібно було розкрити інший дів на основі вибору

Ось як це можна зробити з синтаксисом 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()
        }
    })
})
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.