J'ai un select2 v4.0.0 en cours de remplissage d'un tableau Ajax. Si je règle le val du select2, je peux voir via le débogage javascript qu'il a sélectionné le bon élément (n ° 3 dans mon cas), mais cela ne s'affiche pas dans la zone de sélection, il affiche toujours le paramètre fictif.
Alors que je devrais voir quelque chose comme ça:
Dans mes champs de formulaire:
<input name="creditor_id" type="hidden" value="3">
<div class="form-group minimal form-gap-after">
<span class="col-xs-3 control-label minimal">
<label for="Creditor:">Creditor:</label>
</span>
<div class="col-xs-9">
<div class="input-group col-xs-8 pull-left select2-bootstrap-prepend">
<select class="creditor_select2 input-xlarge form-control minimal select2 col-xs-8">
<option></option>
</select>
</div>
</div>
</div>
Mon javascript:
var initial_creditor_id = "3";
$(".creditor_select2").select2({
ajax: {
url: "/admin/api/transactions/creditorlist",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term,
c_id: initial_creditor_id,
page: params.page
};
},
processResults: function (data, page) {
return {
results: data
};
},
cache: true
},
placeholder: "Search for a Creditor",
width: "element",
theme: "bootstrap",
allowClear: true
}).on("select2:select", function (e) {
var selected = e.params.data;
if (typeof selected !== "undefined") {
$("[name='creditor_id']").val(selected.creditor_id);
$("#allocationsDiv").hide();
$("[name='amount_cash']").val("");
$("[name='amount_cheque']").val("");
$("[name='amount_direct']").val("");
$("[name='amount_creditcard']").val("");
}
}).on("select2:unselecting", function (e) {
$("form").each(function () {
this.reset()
});
("#allocationsDiv").hide();
$("[name='creditor_id']").val("");
}).val(initial_creditor_id);
Comment puis-je faire en sorte que la zone de sélection affiche l'élément sélectionné plutôt que l'espace réservé? Devrais-je envoyer cela dans le cadre de la réponse JSON AJAX peut-être?
Auparavant, Select2 nécessitait une option appelée initSelection qui était définie chaque fois qu'une source de données personnalisée était utilisée, ce qui permettait de déterminer la sélection initiale du composant. Cela a bien fonctionné pour moi dans la v3.5.
Vous faites la plupart des choses correctement, il semble que le seul problème que vous rencontrez est de ne pas déclencher la méthode change
après avoir défini la nouvelle valeur. Sans un événement change
, Select2 ne peut pas savoir que la valeur sous-jacente a changé et affiche uniquement le paramètre fictif. Changer votre dernière partie en
.val(initial_creditor_id).trigger('change');
Devrait résoudre votre problème, et vous devriez voir la mise à jour de l'interface utilisateur immédiatement.
Cela suppose que vous avez déjà un <option>
qui a un value
sur initial_creditor_id
. Si vous ne sélectionnez pas Select2, le navigateur ne pourra pas réellement modifier la valeur car il n'y a pas d'option pour basculer sur et Select2 ne détectera pas la nouvelle valeur. J'ai remarqué que votre <select>
ne contient qu'une seule option, celle de l'espace réservé, ce qui signifie que vous devrez créer le nouveau <option>
manuellement.
var $option = $("<option selected></option>").val(initial_creditor_id).text("Whatever Select2 should display");
Et ensuite, ajoutez-le au <select>
sur lequel vous avez initialisé Select2. Vous devrez peut-être obtenir le texte d'une source externe, c'est-à-dire l'endroit où initSelection
était utilisé, ce qui est toujours possible avec Select2 4.0.0. Comme pour une sélection standard, cela signifie que vous allez devoir faire la demande AJAX pour récupérer la valeur, puis définir le texte <option>
à la volée pour l'ajuster.
var $select = $('.creditor_select2');
$select.select2(/* ... */); // initialize Select2 and any events
var $option = $('<option selected>Loading...</option>').val(initial_creditor_id);
$select.append($option).trigger('change'); // append the option and update Select2
$.ajax({ // make the request for the selected data object
type: 'GET',
url: '/api/for/single/creditor/' + initial_creditor_id,
dataType: 'json'
}).then(function (data) {
// Here we should have the data object
$option.text(data.text).val(data.id); // update the text that is displayed (and maybe even the value)
$option.removeData(); // remove any caching data that might be associated
$select.trigger('change'); // notify JavaScript components of possible changes
});
Bien que cela puisse paraître beaucoup de code, il s'agit de exactement comme vous le feriez pour les zones de sélection autres que Select2 afin de garantir que toutes les modifications ont été apportées.
Ce que j'ai fait est plus propre et doit créer deux tableaux:
J'initialise select2 en utilisant le premier tableau en tant que données et le second en tant que val.
Un exemple de fonction avec pour paramètres un dict of id: name.
function initMyList(values) {
var selected = [];
var initials = [];
for (var s in values) {
initials.Push({id: s, name: values[s].name});
selected.Push(s);
}
$('#myselect2').select2({
data: initials,
ajax: {
url: "/path/to/value/",
dataType: 'json',
delay: 250,
data: function (params) {
return {
term: params.term,
page: params.page || 1,
};
},
processResults: function (data, params) {
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 30) < data.total_count
}
};
},
cache: true
},
minimumInputLength: 1,
tokenSeparators: [",", " "],
placeholder: "Select none, one or many values",
templateResult: function (item) { return item.name; },
templateSelection: function (item) { return item.name; },
matcher: function(term, text) { return text.name.toUpperCase().indexOf(term.toUpperCase()) != -1; },
});
$('#myselect2').val(selected).trigger('change');
}
Vous pouvez alimenter la valeur initiale en utilisant des appels ajax et utiliser jquery pour effectuer l'initialisation de select2.
Le fait d'être forcé à trigger('change')
m'a rendu fou, car j'avais un code personnalisé dans le déclencheur change
, qui ne devrait se déclencher que lorsque l'utilisateur modifie l'option dans le menu déroulant. IMO, le changement ne doit pas être déclenché lors de la définition d'une valeur d'initialisation au début.
J'ai creusé profondément et trouvé ce qui suit: https://github.com/select2/select2/issues/362
Exemple:
$dropDown.val(1).trigger('change.select2');
Ça marche pour moi ...
N'utilisez pas jQuery, uniquement HTML: créez la valeur d'option que vous afficherez comme sélectionné . Si ID est en , sélectionnez 2 données , il sera automatiquement sélectionné.
<select id="select2" name="mySelect2">
<option value="mySelectedValue">
Hello, I'm here!
</option>
</select>
Un scénario auquel les gens n'ont pas vraiment répondu est la suivante: comment créer une présélection lorsque les options sont AJAX et que vous pouvez en sélectionner plusieurs. Puisqu'il s'agit de la page de destination de la présélection AJAX, je vais ajouter ma solution ici.
$('#mySelect').select2({
ajax: {
url: endpoint,
dataType: 'json',
data: [
{ // Each of these gets processed by fnRenderResults.
id: usersId,
text: usersFullName,
full_name: usersFullName,
email: usersEmail,
image_url: usersImageUrl,
selected: true // Causes the selection to actually get selected.
}
],
processResults: function(data) {
return {
results: data.users,
pagination: {
more: data.next !== null
}
};
}
},
templateResult: fnRenderResults,
templateSelection: fnRenderSelection, // Renders the result with my own style
selectOnClose: true
});
Si vous utilisez templateSelection et ajax, certaines de ces autres réponses risquent de ne pas fonctionner. Il semble que la création d'un nouvel élément option
et la définition de value
et text
ne satisferont pas la méthode du modèle lorsque vos objets de données utilisent d'autres valeurs que id et text.
Voici ce qui a fonctionné pour moi:
$("#selectElem").select2({
ajax: { ... },
data: [YOUR_DEFAULT_OBJECT],
templateSelection: yourCustomTemplate
}
Découvrez le jsFiddle ici: https://jsfiddle.net/shanabus/f8h1xnv4
Dans mon cas, je devais entrer processResults
car mes données ne contenaient pas les champs id
et text
requis. Si vous avez besoin de le faire, vous devrez également exécuter votre sélection initiale via la même fonction. Ainsi:
$(".js-select2").select2({
ajax: {
url: SOME_URL,
processResults: processData
},
data: processData([YOUR_INIT_OBJECT]).results,
minimumInputLength: 1,
templateSelection: myCustomTemplate
});
function processData(data) {
var mapdata = $.map(data, function (obj) {
obj.id = obj.Id;
obj.text = '[' + obj.Code + '] ' + obj.Description;
return obj;
});
return { results: mapdata };
}
function myCustomTemplate(item) {
return '<strong>' + item.Code + '</strong> - ' + item.Description;
}
après avoir passé quelques heures à chercher une solution, j'ai décidé de créer la mienne. Il c'est:
function CustomInitSelect2(element, options) {
if (options.url) {
$.ajax({
type: 'GET',
url: options.url,
dataType: 'json'
}).then(function (data) {
element.select2({
data: data
});
if (options.initialValue) {
element.val(options.initialValue).trigger('change');
}
});
}
}
Et vous pouvez initialiser les sélections en utilisant cette fonction:
$('.select2').each(function (index, element) {
var item = $(element);
if (item.data('url')) {
CustomInitSelect2(item, {
url: item.data('url'),
initialValue: item.data('value')
});
}
else {
item.select2();
}
});
Et bien sûr, voici le code HTML:
<select class="form-control select2" id="test1" data-url="mysite/load" data-value="123"></select>
https://github.com/select2/select2/issues/4272 seulement cela a résolu mon problème. Même si vous définissez la valeur par défaut par option, vous devez formater l'objet, qui a l'attribut text et c'est ce que vous souhaitez afficher dans votre option. alors, votre fonction de formatage doit utiliser ||
pour choisir l'attribut qui n'est pas vide.
Créer un combo ajax simple avec la valeur sélectionnée initialement pour select2 4.0.3
<select name="mycombo" id="mycombo""></select>
<script>
document.addEventListener("DOMContentLoaded", function (event) {
selectMaker.create('table', 'idname', '1', $("#mycombo"), 2, 'type');
});
</script>
bibliothèque .js
var selectMaker = {
create: function (table, fieldname, initialSelected, input, minimumInputLength = 3, type ='',placeholder = 'Select a element') {
if (input.data('select2')) {
input.select2("destroy");
}
input.select2({
placeholder: placeholder,
width: '100%',
minimumInputLength: minimumInputLength,
containerCssClass: type,
dropdownCssClass: type,
ajax: {
url: 'ajaxValues.php?getQuery=true&table=' + table + '&fieldname=' + fieldname + '&type=' + type,
type: 'post',
dataType: 'json',
contentType: "application/json",
delay: 250,
data: function (params) {
return {
term: params.term, // search term
page: params.page
};
},
processResults: function (data) {
return {
results: $.map(data.items, function (item) {
return {
text: item.name,
id: item.id
}
})
};
}
}
});
if (initialSelected>0) {
var $option = $('<option selected>Cargando...</option>').val(0);
input.append($option).trigger('change'); // append the option and update Select2
$.ajax({// make the request for the selected data object
type: 'GET',
url: 'ajaxValues.php?getQuery=true&table=' + table + '&fieldname=' + fieldname + '&type=' + type + '&initialSelected=' + initialSelected,
dataType: 'json'
}).then(function (data) {
// Here we should have the data object
$option.text(data.items[0].name).val(data.items[0].id); // update the text that is displayed (and maybe even the value)
$option.removeData(); // remove any caching data that might be associated
input.trigger('change'); // notify JavaScript components of possible changes
});
}
}
};
et le côté serveur php
<?php
if (isset($_GET['getQuery']) && isset($_GET['table']) && isset($_GET['fieldname'])) {
//parametros carga de petición
parse_str(file_get_contents("php://input"), $data);
$data = (object) $data;
if (isset($data->term)) {
$term = pSQL($data->term);
}else{
$term = '';
}
if (isset($_GET['initialSelected'])){
$id =pSQL($_GET['initialSelected']);
}else{
$id = '';
}
if ($_GET['table'] == 'mytable' && $_GET['fieldname'] == 'mycolname' && $_GET['type'] == 'mytype') {
if (empty($id)){
$where = "and name like '%" . $term . "%'";
}else{
$where = "and id= ".$id;
}
$rows = yourarrayfunctionfromsql("SELECT id, name
FROM yourtable
WHERE 1 " . $where . "
ORDER BY name ");
}
$items = array("items" => $rows);
$var = json_encode($items);
echo $var;
?>
Pour une solution simple et sémantique, je préfère définir la valeur initiale en HTML, par exemple:
<select name="myfield" data-placeholder="Select an option">
<option value="initial-value" selected>Initial text</option>
</select>
Ainsi, lorsque j'appelle $('select').select2({ ajax: {...}});
, la valeur initiale est initial-value
et le texte de son option est Initial text
.
Ma version actuelle de Select2 est 4.0. , mais je pense que sa compatibilité avec les autres versions est excellente.
J'ajoute cette réponse principalement parce que je ne peux pas commenter ci-dessus! J'ai trouvé que c'était le commentaire de @ Nicki et son jsfiddle, https://jsfiddle.net/57co6c95/ , qui a finalement permis à ce travail de fonctionner pour moi.
Entre autres choses, il donnait des exemples du format du json nécessaire. Le seul changement que j’ai dû faire est que mes premiers résultats ont été renvoyés dans le même format que l’autre appel ajax.
$option.text(data[0].text).val(data[0].id);
plutôt que
$option.text(data.text).val(data.id);