Подтвердить что ты не робот

Обновите данные select2 без перестройки элемента управления

Я преобразовываю <input type="hidden"> в выпадающий список select2 и подаю его через метод запроса

$('#inputhidden').select2({
    query: function( query ) {
        query.callback( data ); // the data is in the format select2 expects and all works well..
    );
});

Проблема в том, что мне нужно взломать пользовательский интерфейс select2 и поместить две кнопки поверх строки поиска, которые при нажатии будут выполнять вызовы ajax и должны будут обновить содержимое select2.

enter image description here

Теперь мне нужны эти обновления, чтобы не перестраивать select2 полностью, а просто обновлять элементы в раскрывающемся списке. Я не могу найти способ передать новый набор данных уже созданному элементу управления select2, возможно ли это?

4b9b3361

Ответ 1

select2 v3.x

Если у вас есть локальный массив с параметрами (полученный вызовом ajax), я думаю, вам следует использовать параметр data качестве функции, возвращающей результаты для поля выбора:

var pills = [{id:0, text: "red"}, {id:1, text: "blue"}]; 

$('#selectpill').select2({
    placeholder: "Select a pill",
    data: function() { return {results: pills}; }
});

$('#uppercase').click(function() {
    $.each(pills, function(idx, val) {
        pills[idx].text = val.text.toUpperCase();
    });
});
$('#newresults').click(function() {
    pills = [{id:0, text: "white"}, {id:1, text: "black"}];
});

Скрипка: http://jsfiddle.net/RVnfn/576/

В случае, если настроить ВЫБ .2 интерфейс с кнопками, просто вызовите updateResults (этот метод не позволил звонить из OutSite из ВЫБ .2 объекта, но вы можете добавить его в allowedMethods массив в выбор2, если вам нужно) метод после updateting массива данных (таблетки в примере),


select2 v4: пользовательский адаптер данных

Пользовательский адаптер данных с дополнительными updateOptions (неясно, почему в оригинальном ArrayAdapter отсутствует эта функциональность) можно использовать для динамического обновления списка параметров (все параметры в этом примере):

$.fn.select2.amd.define('select2/data/customAdapter',
    ['select2/data/array', 'select2/utils'],
    function (ArrayAdapter, Utils) {
        function CustomDataAdapter ($element, options) {
            CustomDataAdapter.__super__.constructor.call(this, $element, options);
        }
        Utils.Extend(CustomDataAdapter, ArrayAdapter);
        CustomDataAdapter.prototype.updateOptions = function (data) {
            this.$element.find('option').remove(); // remove all options
            this.addOptions(this.convertToOptions(data));
        }        
        return CustomDataAdapter;
    }
);

var customAdapter = $.fn.select2.amd.require('select2/data/customAdapter');

var sel = $('select').select2({
    dataAdapter: customAdapter,
    data: pills
});

$('#uppercase').click(function() {
    $.each(pills, function(idx, val) {
        pills[idx].text = val.text.toUpperCase();
    });
    sel.data('select2').dataAdapter.updateOptions(pills);
});

Скрипка: https://jsfiddle.net/xu48n36c/1/


select2 v4: транспортная функция ajax

в v4 вы можете определить собственный метод транспорта, который может работать с локальным массивом данных (например, спасибо @Caleb_Kiage, я играл с ним без успеха)

документы: https://select2.github.io/options.html#can-an-ajax-plugin-other-than-jqueryajax-be-used

Select2 использует метод транспорта, определенный в ajax.transport, для отправки запросов вашему API. По умолчанию этот метод транспорта - jQuery.ajax, но его можно изменить.

$('select').select2({
    ajax: {
        transport: function(params, success, failure) {
            var items = pills;
            // fitering if params.data.q available
            if (params.data && params.data.q) {
                items = items.filter(function(item) {
                    return new RegExp(params.data.q).test(item.text);
                });
            }
            var promise = new Promise(function(resolve, reject) {
                resolve({results: items});
            });
            promise.then(success);
            promise.catch(failure);
        }
    }
});

НО этим методом вам нужно изменить идентификаторы опций, если текст опции в массиве изменяется - внутренний список элементов опции select2 dom не изменился. Если идентификатор опции в массиве остается прежним - предыдущая сохраненная опция будет отображаться вместо обновления из массива! Это не проблема, если массив изменяется только путем добавления в него новых элементов - хорошо для большинства распространенных случаев.

Скрипка: https://jsfiddle.net/xu48n36c/3/

Ответ 2

Я думаю, что достаточно передать данные напрямую:

$("#inputhidden").select2("data", data, true);

Обратите внимание, что второй параметр указывает, что требуется обновление.

Спасибо @Bergi за помощь в этом.


Если это не будет автоматически обновляться, вы можете попробовать напрямую вызвать метод updateResults.

$("#inputhidden").select2("updateResults");

Или вызвать его косвенно, посылая триггер на "input.select2-input" следующим образом:

var search = $("#inputhidden input.select2-input");
search.trigger("input");

Ответ 3

Используя Select2 4.0 с Meteor, вы можете сделать что-то вроде этого:

Template.TemplateName.rendered = ->

  $("#select2-el").select2({
    data  : Session.get("select2Data")
  })

  @autorun ->

    # Clear the existing list options. 
    $("#select2-el").select2().empty()

    # Re-create with new options.
    $("#select2-el").select2({
      data  : Session.get("select2Data")
    })

Что происходит:

  • При создании шаблона...
  • Инициировать элемент управления select2 с данными из сеанса.
  • Функция @autorun (this.autorun) запускается каждый раз, когда изменяется значение Session.get( "select2Data" ).
  • Всякий раз, когда сеанс изменяется, очищайте существующие опции select2 и создавайте новые данные.

Это работает для любого реактивного источника данных, такого как Collection.find(). fetch() - не просто Session.get().

ПРИМЕЧАНИЕ. Начиная с версии Select2 версии 4.0 вы должны удалить существующие параметры перед добавлением новых onces. Подробнее об этом проблемах GitHub. Нет способа "обновить параметры" без очистки существующих.

Вышеприведено coffeescript. Очень похоже на Javascript.

Ответ 4

Я решил эту проблему, используя параметр ajax и указав настраиваемую транспортную функцию.

см. эту скрипту демо-версия Select2

Вот соответствующие js, чтобы заставить это работать.

var $items = [];

let options = {
ajax: {
    transport: function(params, success, failure) {
    let items = $items;

    if (params.data && params.data.q) {
        items = items.filter(function(item) {
        return new RegExp(params.data.q).test(item.text);
        });
    }

    let promise = new Promise(function(resolve, reject) {
        resolve({
        results: items
        });
    });

    promise.then(success);
    promise.catch(failure);
    }
},
placeholder: 'Select item'
};

$('select').select2(options);

let count = $items.length + 1;

$('button').on('click', function() {
$items.push({
    id: count,
    text: 'Item' + count
});
count++;
});

Ответ 5

var selBoxObj = $('#selectpill');
selBoxObj.trigger("change.select2");

Ответ 6

Попробуй это:

var data = [{id: 1, text: 'First'}, {id: 2, text: 'Second'}, {...}];
$('select[name="my_select"]').empty().select2({
    data: data
});

Ответ 7

Насколько я могу судить, невозможно обновить опции select2 без обновления всего списка или ввода некоторого текста поиска и использования функции запроса.

Что должны делать эти кнопки? Если они используются для определения опций выбора, почему бы не поместить их за пределы поля выбора и попросить их программно установить данные окна выбора и затем открыть его? Я не понимаю, почему вы хотите разместить их поверх окна поиска. Если пользователь не должен искать, вы можете использовать параметр minimumResultsForSearch, чтобы скрыть функцию поиска.

Изменить: как насчет этого...

HTML

<input type="hidden" id="select2" class="select" />

Javascript

var data = [{id: 0, text: "Zero"}],
    select = $('#select2');

select.select2({
  query: function(query) {
    query.callback({results: data});
  },
  width: '150px'
});

console.log('Opening select2...');
select.select2('open');

setTimeout(function() {
  console.log('Updating data...');
  data = [{id: 1, text: 'One'}];
}, 1500);

setTimeout(function() {
  console.log('Fake keyup-change...');
  select.data().select2.search.trigger('keyup-change');
}, 3000);

Пример: Plunker

Изменить 2:. По крайней мере, это позволит обновить список, однако есть еще какая-то странность, если вы ввели текст поиска перед запуском события keyup-change.

Ответ 8

Для Select2 4.X

var instance = $('#select2Container').data('select2');
var searchVal = instance.dropdown.$search.val();
instance.trigger('query', {term:searchVal});