Actualizar datos select2 sin reconstruir el control

Estoy convirtiendo un en un menú desplegable de select2 y alimentándolo a través del método de consulta

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

El problema es que necesito hackear la interfaz de usuario select2 y colocar dos botones en la parte superior de la barra de búsqueda que, al hacer clic, realizará llamadas ajax y tendrá que actualizar el contenido de select2.

enter image description here

Ahora, necesito que esas actualizaciones ocurran sin reconstruir completamente el select2, sino simplemente actualizar los elementos en el menú desplegable. No puedo encontrar una manera de pasar un nuevo conjunto de datos a un control de selección2 ya creado, ¿es posible?

    select2 v3.x

    Si tiene una matriz local con opciones (recibidas por una llamada ajax), creo que debería usar data parámetro de data como función que devuelve resultados para el cuadro de selección:

     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/

    En caso de que personalice la interfaz select2 con botones, simplemente llame a updateResults (este método no permite llamar desde fuera del objeto select2 pero puede agregarlo a la matriz allowedMethods en select2 si es necesario) después de actualizar la matriz de datos (pastillas en el ejemplo) .


    select2 v4: adaptador de datos personalizado

    El adaptador de datos personalizado con updateOptions adicionales (no está claro por qué el ArrayAdapter original carece de esta funcionalidad) se puede usar para actualizar dinámicamente la lista de opciones (todas las opciones en este ejemplo):

     $.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: función de transporte ajax

    en v4 puedes definir un método de transporte personalizado que pueda funcionar con una matriz de datos local (thx @Caleb_Kiage, por ejemplo, lo he jugado sin éxito)

    documentos: https://select2.github.io/options.html#can-an-ajax-plugin-other-than-jqueryajax-be-used

    Select2 usa el método de transporte definido en ajax.transport para enviar solicitudes a su API. Por defecto, este método de transporte es jQuery.ajax, pero esto se puede cambiar.

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

    PERO con este método necesita cambiar los identificadores de las opciones si el texto de la opción en la matriz cambia – la lista de elementos de la opción interna select2 dom no se modificó. Si id of option in array permanece igual – ¡se mostrará la opción guardada anterior en lugar de actualizarse desde la matriz! Eso no es un problema si la matriz se modifica solo al agregarle nuevos elementos , vale para la mayoría de los casos comunes.

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

    Creo que es suficiente entregar los datos directamente:

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

    Tenga en cuenta que el segundo parámetro parece indicar que se desea una actualización.

    Gracias a @Bergi por su ayuda con esto .


    Si eso no se actualiza automáticamente, puede intentar llamarlo directamente al método updateResults.

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

    O activarlo indirectamente enviando un disparador a “input.select2-input” como sigue:

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

    Usando Select2 4.0 con Meteor puedes hacer algo como esto:

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

    Qué esta pasando:

    1. Cuando la plantilla se representa …
    2. Inicie un control select2 con datos de Session.
    3. La función @autorun (this.autorun) se ejecuta cada vez que cambia el valor de Session.get (“select2Data”).
    4. Cuando la sesión cambie, borre las opciones existentes de select2 y vuelva a crear con los datos nuevos.

    Esto funciona para cualquier fuente de datos reactiva, como Collection.find (). Fetch () – no solo Session.get ().

    NOTA: a partir de la versión 4.0 de Select2, debe eliminar las opciones existentes antes de agregar nuevas onces. Vea este Issue de GitHub para más detalles . No hay un método para ‘actualizar las opciones’ sin borrar las existentes.

    Lo anterior es coffeescript. Muy similar para Javascript.

    Resolví este problema usando la opción ajax y especificando una función de transporte personalizada.

    ver esta demo de opciones dinámicas Select2 de violín

    Aquí está el js relevante para hacer que esto funcione.

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

    Lo mejor que puedo decir es que no es posible actualizar las opciones de select2 sin actualizar toda la lista o ingresar texto de búsqueda y usar una función de consulta.

    ¿Qué se supone que deben hacer esos botones? Si se utilizan para determinar las opciones de selección, ¿por qué no ponerlos fuera del cuadro de selección y hacer que configuren programáticamente los datos del cuadro de selección y luego lo abran? No entiendo por qué querrías ponerlos encima del cuadro de búsqueda. Si se supone que el usuario no debe buscar, puede usar la opción minimumResultsForSearch para ocultar la función de búsqueda.

    Editar : ¿Qué tal esto …

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

    Ejemplo : Plunker

    Edición 2: Al menos conseguirá que actualice la lista, sin embargo, todavía hay algunas rarezas si ha ingresado texto de búsqueda antes de activar el keyup-change .

    Para Select2 4.X

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