Прикрепите событие клика к элементу в .select2-result

Я ищу способ прикрепить событие click к элементу select2-result. Я пошел дальше и отформатировал как результат, так и выбор через

function format(state) {
    if (!state.id) return state.text; // optgroup
    return state.text + " <i class='info'>link</i>";
}

чтобы добавить значок «информация». Теперь я пытаюсь прикрепить простое событие щелчка к элементу .info, но не могу заставить это работать:

$('.info').on('click', function(event){
    event.preventDefault();
    alert("CLICK");
    $('#log').text( "clicked" );
});

Любая помощь? Кто-нибудь с похожей проблемой? Это вообще возможно?

Я подготовил jsFiddle по адресу: http://jsfiddle.net/s2dqh/3/.


person brckmann    schedule 26.03.2013    source источник
comment
вы хотите, чтобы событие клика происходило во всем элементе или только в ссылке?   -  person Arun P Johny    schedule 26.03.2013
comment
просто ссылка, Арун - исходная функциональность select2 (выбор опции из раскрывающегося списка) должна быть сохранена   -  person brckmann    schedule 26.03.2013
comment
В версии select2 3.3 этой проблемы нет   -  person bizauto    schedule 15.10.2014


Ответы (12)


Поскольку библиотека Select2 предотвращает любые события щелчка в всплывающем списке, вы не можете напрямую привязывать события к .info. Но вы можете переопределить метод onSelect и поместить туда любой код, какой захотите.

См. пример: http://jsfiddle.net/f8q2by55/

Обновление для множественного выбора: http://jsfiddle.net/6jaodjzq/

person ant_Ti    schedule 26.03.2013
comment
превосходно, пока спасибо; я знаю, что это превышает мой первоначальный вопрос, но как мне заставить ссылку в .select2-choice наследовать такое же поведение? (чтобы уточнить: .select2-choice - это выбранный элемент - jsfiddle показывает, что событие щелчка работает только для раскрывающихся опций, а не для выбранного в данный момент элемента) - person brckmann; 26.03.2013
comment
@ant_Ti - я столкнулся со слишком многими проблемами с грязным взломом (выпадающий список select2 не закрывается и т. д.), поэтому я пошел дальше и реализовал обходной путь для информационного значка .select2-choice, который делает то, что ему нужно, не мешая с оригинальной функциональностью select2. Позвольте мне еще один вопрос относительно первого решения (перезапись «onSelect»): я заметил, что при выборе с помощью клавиши возврата это приводит к Uncaught TypeError: не удается прочитать свойство «цель» неопределенного - любые подсказки, как это поймать последнее раздражение? - person brckmann; 01.04.2013
comment
@ant_Ti - Большое спасибо за быстрый ответ (работает как шарм!), действительно многому здесь научился! Позвольте мне еще один вопрос: как мне применить измененный onSelect к другим экземплярам select2? - person brckmann; 02.04.2013
comment
Я забыл добавить, что каждый из экземпляров select2 имеет разные параметры. Рад открыть еще один вопрос для этого! - person brckmann; 02.04.2013
comment
@brckmann смотрите мое обновление, чтобы ответить. Небольшой рефакторинг вашего кода - person ant_Ti; 02.04.2013
comment
У меня также были проблемы с этим решением, после первого нажатия на информацию некоторые вещи не работают. Особенно при использовании с x-редактируемым select2. Выкладываю альтернативное решение. - person AaronLS; 13.06.2013
comment
Я использую нокаут + select2, и у меня есть базовый обработчик привязки. Как использовать событие onSelect? - person robasta; 14.11.2013
comment
Событие @rob onSelect является пользовательским событием библиотеки, поэтому я думаю, что не должно быть никаких изменений. - person ant_Ti; 18.11.2013

Это похоже на концепцию netme, но событие select2 неверно (возможно, разница в версии), и вам нужно использовать stopPropagation, чтобы предотвратить выбор элемента:

http://jsfiddle.net/ZhfMg/

$('#mySelect2').on('select2-open', function() { 
    $('.select2-results .info').on('mouseup', function(e) { 
        e.stopPropagation();
        console.log('clicked');
    }); 
});

Если используется с x-editable. Это происходит, когда x-editable переходит в режим редактирования (показано событие), когда существует select2, и вы можете подключиться к его функции открытия.

$('#myXEditable').on('shown', function () {
    $(this).data('editable').input.$input.on('select2-open', function() { 
        $('.select2-results .info').on('mouseup', function(e) { 
            e.stopPropagation();
            console.log('clicked');
        }); 
    });
});
person AaronLS    schedule 12.06.2013
comment
+1 Общая часть $('#mySelect2').on('select2-open', function() { сэкономила мне время при создании пользовательского кода для моих нужд. - person Michel Ayres; 22.04.2014
comment
Ответ @MichelAyres - единственное, что сработало для меня. - person lammy; 07.03.2017

Для версий Select2 до 4.0.0 (то есть 3.5.x и ниже) вы должны обратиться к этот ответ о привязке к onSelect.

В новых версиях Select2 события больше не уничтожаются в результатах, поэтому вы можете просто привязываться к событиям mouseup/mousedown, как обычно. Вам следует избегать привязки к событию click, потому что по умолчанию браузеры его не вызывают.

$(".select2").select2({
  templateResult: function (data) {
    if (data.id == null) {
      return data.text;
    }
    
    var $option = $("<spam></span>");
    var $preview = $("<a target='_blank'> (preview)</a>");
    $preview.prop("href", data.id);
    $preview.on('mouseup', function (evt) {
      // Select2 will remove the dropdown on `mouseup`, which will prevent any `click` events from being triggered
      // So we need to block the propagation of the `mouseup` event
      evt.stopPropagation();
    });
    
    $preview.on('click', function (evt) {
      console.log('the link was clicked');
    });
    
    $option.text(data.text);
    $option.append($preview);
    
    return $option;
  }
});
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.js"></script>

<select class="select2" style="width: 200px;">
  <option value="https://google.com">Google</option>
  <option value="https://mail.google.com">GMail</option>
</select>

В этом примере мы останавливаем распространение события mouseup, поэтому браузер инициирует событие click. Если вы не работаете с реальными ссылками, а вместо этого вам нужно просто поймать событие click, вы должны просто подключиться к событию mouseup.

person Kevin Brown    schedule 09.08.2015

использовать триггер события select2select по умолчанию вместо использования других событий jquery

$('#mySelect2').on('select2:select', function (e) {
    var data = e.params.data;
    console.log(data);
});

для получения более подробной информации см. ссылку ниже https://select2.org/programmatic-control/events

person Balakrishnan Bsk    schedule 08.08.2019

Ни один из приведенных выше ответов не работал у меня для select2 4.0.0, так что вот что я в итоге сделал:

$(document).on('mouseup', '.select2-container--open .select2-results__option', function (e) {
    // Act on the element
}

В частности, я хотел воздействовать только на ранее выбранный элемент:

$(document).on('mouseup', '.select2-container--open .select2-results__option[aria-selected=true]', function (e) {
    // Do something on the previously-selected item
}
person Aegix    schedule 23.12.2015
comment
Если вы можете предоставить JSfiddle или что-то еще, чтобы доказать, что ваш подход работает. Здесь слишком много ответов, которые не работают для новой версии select2. - person Yevgeniy Afanasyev; 06.01.2016

Более простой подход в соответствии с документами.

$('#mySelect2').on('select2:select', function (e) {
    var data = e.params.data;
    console.log(data);
});

Удивлен, что не увидел ответа на этот вопрос.

person HalfWebDev    schedule 13.10.2017
comment
Если вы выберете по какой-либо причине 2 раза одну и ту же опцию, она не сработает. - person Federico Navarrete; 01.02.2018

Просто добавьте прослушиватель «open» и настройте другой прослушиватель «mouseup» для тега «»:

$("#select").on('open', function() { 
    $('.select2-results i').on('mouseup', function() { 
       alert('aaa');
    }); 
});

Вот ссылка на мое решение: http://jsfiddle.net/EW8t7/

person Mikhail Chernykh    schedule 26.03.2013
comment
К сожалению, с этим ответом нажатие на ссылку приводит к выбору элемента и закрытию раскрывающегося списка. Не имеет функции предотвращения по умолчанию. - person AaronLS; 11.06.2013

Я думаю, что обработка Select2 события mouseup не позволяет элементу .info получать событие click. Наличие элемента .info, фиксирующего событие mouseup и предотвращающего его распространение, похоже, исправляет это.

function format(state, container) {
    if (!state.id) return state.text; // optgroup
    container.append(state.text);
    $('<i class="info">link</i>')
        .appendTo(container)
        .mouseup(function(e) {
            e.stopPropagation();            
        })
        .click(function(e) {
            e.preventDefault();
            alert('CLICK');
        });
}

Это также можно сделать для поддержки ссылки в выбранном элементе, но здесь необходимо захватить событие mousedown.

jsfiddle

person John S    schedule 27.11.2014
comment
Для меня сработало событие mousedown (как в вашей функции скрипки formatSelection), а не mouseup - person Pascal Luxain; 13.02.2015
comment
@yezahel - Спасибо. Мой jsfiddle использует версию 3.3.1, которая использовалась в вопросе. Последняя версия — 3.5.2, и, к сожалению, я думаю, вы правы в том, что код для этой работы должен немного отличаться для этой версии. - person John S; 13.02.2015

Вам нужно отвязать событие mouseup от элемента .select2-results__options. Я делаю это в своей функции templateResult:

function templateResult(location) {

    var $location = $([html with links]);

    $('.select2-results__options').unbind('mouseup');

    return $location;
}

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

$('.select2-results__options').unbind('mouseup');

$('a', $location).on('click', function (e) {
    $('#locations_dropdown').select2('val', location.id);
    $('#locations_dropdown').select2('close');
});

return $location;
person divups    schedule 08.07.2015
comment
Это будет работать только для стандартных выборок, где <option> уже существует заранее. И поскольку вы используете 4.0.0, вы должны использовать .val(location.id).trigger('change') вместо старого метода select2('val'). - person Kevin Brown; 09.08.2015

дело похоже в том, что tgas будет удаляться сразу после закрытия ящика. Поэтому событие click не может быть запущено.

Я изменил несколько вещей + событие, которое будет прослушиваться. Теперь это мышка...

function format(state) {
    if (!state.id) return state.text; // optgroup
    return state.text + " <a class='info'>link</a>";
}

$("select").select2({
    formatResult: format,
    formatSelection: format,
    escapeMarkup: function(m) { return m; }
}).on('select2-open',function(){
    console.log($('.info'))
    $('.info').on('mousedown', function(event){
        console.log("click")
        $('#log').text( "clicked" );
        event.preventDefault();
    });
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.js"></script>

<select>
  <option>red</option>
  <option>green</option>
  <option>blue</option>
</select>

<div id="log"></div>

person Christian    schedule 26.03.2013
comment
Хорошая идея, но в вашем случае вы не сможете предотвратить закрытие списка, нажав на .info - person ant_Ti; 26.03.2013

Просто столкнулся с этой проблемой с select2 v4.0.3 и в итоге использовал событие select2:selecting. Вот, по сути, как я это сделал:

var $select2 = $savedReportsList.select2({ [stuff] });

$select2.on('select2:selecting', function(e) {
  var args = e.params.args;
  if ($(args.originalEvent.target).hasClass('[something]')) {
    if (confirm('Are you sure?')) {
       window.location = '[somewhere]' + '/' + args.data.id;
    }
    return false; // stops propogation (so select2:select never fires)
  });
});

person etipton    schedule 20.07.2018

Простое событие onchange, подобное этому, также поможет решить проблему.

<select id="GetClientAccounts" class="default-select2 form-control col-md-4" onchange="GetClientAccounts();">
    <option disabled selected value="-1">Select a customer from here</option>
    @{
        if (ViewBag.customers != null)
        {
            foreach (CustomerTBL customer in ((List<CustomerTBL>)ViewBag.customers).OrderBy(c => c.cusCustomerName))
            {
                <option value="@customer.cusCustomerID">@customer.cusCustomerName</option>
            }
        }
    }
</select>
person PraBel    schedule 06.03.2020
comment
Привет, PraBel, когда вы используете стиль кода, ваш пример кода будет легче читать, я думаю - person JanRecker; 06.03.2020