Je suis en train de convertir un <input type="hidden">
en une liste déroulante select2 et de lui transmettre des données via la méthode d'interrogation
$('#inputhidden').select2({
query: function( query ) {
query.callback( data ); // the data is in the format select2 expects and all works well..
);
});
Le problème est que je devais pirater l'interface utilisateur de select2 et positionner deux boutons en haut de la barre de recherche qui, lorsque l'utilisateur clique dessus, effectuera des appels ajax et devra mettre à jour le contenu de select2.
Maintenant, j'ai besoin que ces mises à jour se produisent sans reconstruire entièrement le select2, mais plutôt en rafraîchissant les éléments du menu déroulant. Je n'arrive pas à trouver un moyen de transmettre un nouvel ensemble de données à un contrôle select2 déjà créé, est-ce possible?
Si vous avez un tableau local avec des options (reçu par un appel ajax), je pense que vous devriez utiliser le paramètre data
comme fonction renvoyant les résultats pour la zone de sélection:
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"}];
});
VIOLON: http://jsfiddle.net/RVnfn/576/
Si vous personnalisez l'interface select2 avec des boutons, appelez simplement updateResults
(cette méthode n'est pas autorisée à appeler depuis un objet select de out2 mais vous pouvez l'ajouter à un tableau allowedMethods
dans select2 si nécessaire), méthode après la mise à jour d'un tableau de données (pills par exemple) .
Un adaptateur de données personnalisé avec la méthode updateOptions
supplémentaire (la raison pour laquelle la méthode ArrayAdapter
originale n’a pas cette fonctionnalité) peut être utilisé pour mettre à jour de manière dynamique la liste d’options (toutes les options de cet exemple):
$.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);
});
VIOLON: https://jsfiddle.net/xu48n36c/1/
dans la v4, vous pouvez définir une méthode de transport personnalisée pouvant fonctionner avec un tableau de données local (thx @Caleb_Kiage, par exemple, j'ai joué sans succès)
docs: https://select2.github.io/options.html#can-an-ajax-plugin-other-than-jqueryajax-be-used
Select2 utilise la méthode de transport définie dans ajax.transport pour envoyer demandes à votre API. Par défaut, cette méthode de transport est jQuery.ajax mais cela peut être changé.
$('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);
}
}
});
MAIS avec cette méthode, vous devez modifier les identifiants des options si le texte de l'option dans le tableau est modifié - la liste des éléments d'option opt internes de select2 dom n'a pas été modifiée. Si l'id de l'option dans le tableau reste identique, l'option enregistrée précédemment sera affichée au lieu d'être mise à jour à partir du tableau! Ce n'est pas un problème si array n'est modifié que par l'ajout de nouveaux éléments - ok pour la plupart des cas courants.
FIDDLE: _ https://jsfiddle.net/xu48n36c/3/
Je pense qu'il suffit de transmettre les données directement:
$("#inputhidden").select2("data", data, true);
Notez que le deuxième paramètre semble indiquer qu'une actualisation est souhaitée.
Merci à @Bergi pour son aide avec this .
Si cela ne se met pas automatiquement à jour, vous pouvez aussi appeler directement sa méthode updateResults.
$("#inputhidden").select2("updateResults");
Ou le déclencher indirectement en envoyant un déclencheur à "input.select2-input" comme ceci:
var search = $("#inputhidden input.select2-input");
search.trigger("input");
En utilisant Select2 4.0 avec Meteor, vous pouvez faire quelque chose comme ceci:
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")
})
Que ce passe-t-il:
Cela fonctionne pour toutes les sources de données réactives, telles que Collection.find (). Fetch (), et pas uniquement pour Session.get ().
REMARQUE: à partir de Select2 version 4.0, vous devez supprimer les options existantes avant d’ajouter de nouvelles onces. Voir ce problème GitHub pour plus de détails . Il n'y a pas de méthode pour "mettre à jour les options" sans effacer les options existantes.
Ce qui précède est coffeescript. Très similaire pour Javascript.
J'ai résolu ce problème en utilisant l'option ajax et en spécifiant une fonction de transport personnalisée.
voir ce violon Select2 démo d'options dynamiques
Voici le js pertinent pour que cela fonctionne.
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");
Pour Select2 4.X
var instance = $('#select2Container').data('select2');
var searchVal = instance.dropdown.$search.val();
instance.trigger('query', {term:searchVal});
Autant que je sache, il n’est pas possible de mettre à jour les options de select2 sans actualiser la liste complète ou entrer du texte de recherche et en utilisant une fonction de requête.
Que sont censés faire ces boutons? S'ils sont utilisés pour déterminer les options de sélection, pourquoi ne pas les mettre en dehors de la zone de sélection et les laisser définir par programme les données de la boîte de sélection, puis les ouvrir? Je ne comprends pas pourquoi vous voudriez les mettre en haut du champ de recherche. Si l'utilisateur n'est pas supposé effectuer une recherche, vous pouvez utiliser l'option minimumResultsForSearch pour masquer la fonctionnalité de recherche.
Edit: Qu'en est-il de cela ...
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);
Exemple: Plunker
Edit 2: Cela permettra au moins de mettre la liste à jour, mais il y a toujours quelque chose de bizarre si vous avez saisi un texte de recherche avant de déclencher l'événement keyup-change
.
Essaye celui-là:
var data = [{id: 1, text: 'First'}, {id: 2, text: 'Second'}, {...}];
$('select[name="my_select"]').empty().select2({
data: data
});