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

Я конвертирую в выпадающее меню select2 и подаю его данные методом запроса

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

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

введите описание изображения здесь

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

    select2 v3.x

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

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

    FIDDLE : http://jsfiddle.net/RVnfn/576/

    В случае, если вы настроили интерфейс select2 с помощью кнопок, просто вызовите updateResults (этот метод не разрешен для вызова из outsite объекта select2, но вы можете добавить его в allowedMethods в select2, если вам нужен) после массива данных обновления (например, в примерах) ,


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

    FIDDLE : https://jsfiddle.net/xu48n36c/1/


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

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

    docs: 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 не был изменен. Если id опции в массиве останется прежним – предыдущая сохраненная опция будет отображаться вместо обновления из массива! Это не проблема, если массив изменен только путем добавления к нему новых элементов – нормально для большинства распространенных случаев.

    FIDDLE: https://jsfiddle.net/xu48n36c/3/

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

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

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

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


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

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

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

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

    Используя 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") }) 

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

    1. Когда Шаблон визуализируется …
    2. Инициируйте элемент управления select2 с данными из сеанса.
    3. Функция @autorun (this.autorun) запускается каждый раз, когда изменяется значение Session.get (“select2Data”).
    4. Всякий раз, когда сеанс изменяется, очищайте существующие опции select2 и создавайте новые данные.

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

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

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

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

    см. эту скрипту Select2 dynamic options demo

    Вот соответствующие 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++; }); 

    var selBoxObj = $ (‘# selectpill’); selBoxObj.trigger ( “change.select2”);

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

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

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

    HTML :

      

    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 ключа.

    Для Select2 4.X

     var instance = $('#select2Container').data('select2'); var searchVal = instance.dropdown.$search.val(); instance.trigger('query', {term:searchVal}); 
    Давайте будем гением компьютера.