web-dev-qa-db-fra.com

Ajoutez dynamiquement un élément au contrôle jQuery Select2 qui utilise AJAX

J'ai un contrôle SelectQ jQuery qui utilise AJAX pour peupler:

<input type="text" name="select2" id="select2" style='width:400px' value="999">

var initialSelection = { id: '999', text:"Some initial option"};

$("#select2").select2({
    placeholder: "Select Option",
    minimumInputLength: 2,
    ajax: { 
        url: "/servletToGetMyData",
        dataType: 'json',
        data: function (term, page) { return { term: term }; },
        results: function (data, page) {  return { results: data.results} }
    },
    initSelection : function(element, callback){ callback(initialSelection); },     
    escapeMarkup: function (m) { return m; }
}); 

Le AJAX relie à une base de données d'options possibles et, comme vous pouvez le constater, nécessite deux caractères de saisie.

Le problème est que l'utilisateur peut utiliser une boîte de dialogue pour ajouter une nouvelle option si celle-ci n'existe pas dans la base de données. Au retour de ce dialogue, j'essaie:

var o = $("<option/>", {value: newID, text: newText});
$('#select2').append(o);
$('#select2 option[value="' + newID + '"]').prop('selected',true);
$('#select2').trigger('change');

Mais ça ne marche pas. Le même code exact fonctionne pour les zones Select2 non AJAX. J'ai essayé diverses alternatives, comme utiliser $('#select2').select2("val", newID); mais cela ne fonctionne pas.

J'ai même essayé de supprimer complètement le contrôle Select2. Cependant, $('#select2').remove() ne supprime que le champ <input> d'origine, mais laisse le contrôle Select2 en attente. Notez que la page comporte plusieurs contrôles Select2, je ne peux donc pas utiliser de sélecteur de classe pour les contrôles Select2, car cela supprime les autres contrôles dont j'ai besoin.

Toute idée sur la manière de: a) ajouter dynamiquement une option à un contrôle Select2 utilisant AJAX; ou b) supprimer complètement un contrôle Select2 afin qu'il puisse être ajouté par programme? Ou toute autre solution ...

Edit J'ai trouvé une autre question qui montre comment supprimer un élément select2 en utilisant .select2 ("destroy"). Cela fonctionne mais est, à mon avis, sous-optimal. Je préférerais de beaucoup pouvoir ajouter cette option plutôt que de détruire et de recréer le select2.

45

Cela a fourni une solution simple: Définir les données dans Select2 après insertion avec AJAX

$("#select2").select2('data', {id: newID, text: newText});      
30

C’est beaucoup plus facile à partir de select2 v4. Vous pouvez créer un new Option, et l'ajoute directement à l'élément select. Voir mon codepen ou l'exemple ci-dessous:

$(document).ready(function() {
    $("#state").select2({
      tags: true
    });
      
    $("#btn-add-state").on("click", function(){
      var newStateVal = $("#new-state").val();
      // Set the value, creating a new option if necessary
      if ($("#state").find("option[value=" + newStateVal + "]").length) {
        $("#state").val(newStateVal).trigger("change");
      } else { 
        // Create the DOM option that is pre-selected by default
        var newState = new Option(newStateVal, newStateVal, true, true);
        // Append it to the select
        $("#state").append(newState).trigger('change');
      } 
    });  
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/Twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/css/select2.min.css" rel="stylesheet"/>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/js/select2.min.js"></script>


<select id="state" class="js-example-basic-single" type="text" style="width:90%">
  <option value="AL">Alabama</option>
  <option value="WY">Wyoming</option>
</select>
<br>
<br>
<input id="new-state" type="text" />
<button type="button" id="btn-add-state">Set state value</button>

Astuce: essayez de saisir les valeurs existantes dans la zone de texte, comme "AL" ou "WY". Ensuite, essayez d'ajouter de nouvelles valeurs.

39
alexw

Dans le cas de Select2 Version 4+

sa syntaxe a changé et vous devez écrire comme ceci:

// clear all option
$('#select_with_blank_data').html('').select2({data: [{id: '', text: ''}]});

// clear and add new option
$("#select_with_data").html('').select2({data: [
 {id: '', text: ''},
 {id: '1', text: 'Facebook'},
 {id: '2', text: 'Youtube'},
 {id: '3', text: 'Instagram'},
 {id: '4', text: 'Pinterest'}]});



//  append option
$("#select_with_data").append('<option value="5">Twitter</option>');
$("#select_with_data").val('5');
$("#select_with_data").trigger('change');
18
Sruit A.Suk

Dans Select2 4.0.2

$("#yourId").append("<option value='"+item+"' selected>"+item+"</option>");
$('#yourId').trigger('change'); 
17
Digvijay

J'ai résolu le problème avec l'aide de ce lien http://www.bootply.com/122726 . j'espère vous aider

Ajoutez une option dans select2 jquery et liez votre appel ajax avec l'id de lien créé (#addNew) pour créer une nouvelle option à partir du backend. et le code

 $.getScript('http://ivaynberg.github.io/select2/select2-3.4.5/select2.js',function(){

  $("#mySel").select2({
    width:'240px',
    allowClear:true,
    formatNoMatches: function(term) {
        /* customize the no matches output */
        return "<input class='form-control' id='newTerm' value='"+term+"'><a href='#' id='addNew' class='btn btn-default'>Create</a>"
    }
  })
  .parent().find('.select2-with-searchbox').on('click','#addNew',function(){
    /* add the new term */
    var newTerm = $('#newTerm').val();
    //alert('adding:'+newTerm);
    $('<option>'+newTerm+'</option>').appendTo('#mySel');
    $('#mySel').select2('val',newTerm); // select the new term
    $("#mySel").select2('close');       // close the dropdown
  })

});



<div class="container">
    <h3>Select2 - Add new term when no search matches</h3>
    <select id="mySel">
        <option>One</option>
        <option>Two</option>
        <option>Three</option>
        <option>Four</option>
        <option>Five</option>
        <option>Six</option>
        <option>Twenty Four</option>
    </select>
    <br>
    <br>
</div>
10
Suneel

Étendre la réponse de Bumptious Q Bangwhistle:

$('#select2').append($('<option>', { 
    value: item,
    text : item 
})).select2();

Cela ajouterait les nouvelles options dans le <select> balises et permet à select2 de la restituer.

5
hareluya86

Je l'ai fait de cette façon et cela a fonctionné pour moi comme un charme.

var data = [{ id: 0, text: 'enhancement' }, { id: 1, text: 'bug' }, { id: 2, 

    text: 'duplicate' }, { id: 3, text: 'invalid' }, { id: 4, text: 'wontfix' }];

    $(".js-example-data-array").select2({
      data: data
    })
3
Chaudhry Waqas
$("#my_select").select2('destroy').empty().select2({data: [{id: 1, text: "new_item"}]});
2
Musznik

Pour que le marquage dynamique fonctionne avec ajax, voici ce que j'ai fait.

Sélectionnez la version 3.5

Ceci est facile dans la version 3.5 car il offre le hook createSearchChoice. Cela fonctionne même pour plusieurs sélections, à condition que multiple: true et tags: true sont définis.

HTML

<input type="hidden" name="locations" value="Whistler, BC" />

JS

$('input[name="locations"]').select2({
  tags: true,
  multiple: true,
  createSearchChoice: function(term, data) {
    if (!data.length)
      return { id: term, text: term };
    },
  ajax: {
    url: '/api/v1.1/locations',
    dataType: 'json'
  }
});

L'idée ici est d'utiliser le hook createSearchChoice de select2 qui vous transmet à la fois le term que l'utilisateur a entré et la réponse ajax (sous la forme data). Si ajax renvoie une liste vide, indiquez à select2 de proposer l'option term saisie par l'utilisateur.

Démo: https://johnny.netlify.com/select2-examples/version


Sélectionnez2 version 4.X

La version 4.X n'a ​​plus de hook createSearchChoice, mais voici comment j'ai fait la même chose.

HTML

  <select name="locations" multiple>
    <option value="Whistler, BC" selected>Whistler, BC</option>
  </select>

JS

$('select[name="locations"]').select2({
  ajax: {
    url: '/api/v1.1/locations',
    dataType: 'json',
    data: function(params) {
      this.data('term', params.term);
      return params;
    },
    processResults: function(data) {
      if (data.length)
        return {
          results: data
        };
      else
        return {
          results: [{ id: this.$element.data('term'), text: this.$element.data('term') }]
        };
    }
  }
});

L'idée est de cacher le terme saisi par l'utilisateur dans le magasin de données de jQuery dans le crochet data de select2. Puis, dans le hook processResults de select2, je vérifie si la réponse ajax est vide. Si c'est le cas, je récupère le terme caché que l'utilisateur a saisi et le retourne en tant qu'option pour select2.

Démo: https://johnny.netlify.com/select2-examples/version4

0
Johnny Oshika