Select2 dropdown mais autoriser de nouvelles valeurs par utilisateur?

125

Je veux avoir une liste déroulante avec un ensemble de valeurs mais aussi permettre à l'utilisateur de "sélectionner" une nouvelle valeur qui n'y figure pas.

Je vois que select2 prend en charge cela si vous l'utilisez en tagsmode, mais y a-t-il un moyen de le faire sans utiliser de balises?

John John
la source
1
Select2 n'a jamais fonctionné pour moi, au moins createSearchChoice n'a jamais fonctionné pour moi dans la version 4.0.3, et je ne voulais pas que mes utilisateurs attendent ajax pour terminer pour renvoyer le même mot-clé, j'ai donc dû déployer ma propre bibliothèque, je ne suis que le partager parce que je pense que cela pourrait aider les autres qui sont encore confus comme moi, veuillez ne pas voter si vous n'êtes pas d'accord avec ma réponse: github.com/razzbee/tagcomplete
razzbee

Réponses:

100

Pour la version 4+, vérifiez cette réponse ci-dessous par Kevin Brown

Dans Select2 3.5.2 et ci-dessous, vous pouvez utiliser quelque chose comme:

$(selector).select2({
  minimumInputLength:1,
  "ajax": {
    data:function (term, page) {
      return { term:term, page:page };
    },
    dataType:"json",
    quietMillis:100,
    results: function (data, page) {
      return {results: data.results};
    },
    "url": url
  },
  id: function(object) {
    return object.text;
  },
  //Allow manually entered text in drop down.
  createSearchChoice:function(term, data) {
    if ( $(data).filter( function() {
      return this.text.localeCompare(term)===0;
    }).length===0) {
      return {id:term, text:term};
    }
  },
});

(extrait d'une réponse sur la liste de diffusion select2, mais ne trouve pas le lien maintenant)

fmpwizard
la source
4
Désolé pour la réponse tardive mais merci beaucoup pour votre solution! L'autre affiche, a publié un lien vers votre essence btw qui vous rend doublement génial! :)
johnjohn
rrauenza génial, exactement ce que je cherchais
Matthias S
4
L'ajout de la selectOnBlur: truevolonté fera le travail s'il vous plaît voir: stackoverflow.com/questions/25616520/…
Alireza Fattahi
1
Juste un avertissement pour les futurs lecteurs, vous voudrez probablement utiliser tags: []avec createSearchChoice.
Kevin Brown
5
Le violon lié ci-dessus semble cassé.
Wolfr
175

L' excellente réponse fournie par @fmpwizard fonctionne pour Select2 3.5.2 et versions antérieures, mais elle ne fonctionnera pas dans 4.0.0 .

Depuis très tôt (mais peut-être pas aussi tôt que cette question), Select2 a pris en charge le «marquage»: où les utilisateurs peuvent ajouter leur propre valeur si vous leur permettez. Cela peut être activé via l' tagsoption, et vous pouvez jouer avec un exemple dans la documentation .

$("select").select2({
  tags: true
});

Par défaut, cela créera une option qui a le même texte que le terme de recherche qu'ils ont entré. Vous pouvez modifier l'objet utilisé si vous souhaitez le marquer d'une manière spéciale ou créer l'objet à distance une fois qu'il est sélectionné.

$("select").select2({
  tags: true,
  createTag: function (params) {
    return {
      id: params.term,
      text: params.term,
      newOption: true
    }
  }
});

En plus de servir d'indicateur facile à repérer sur l'objet transmis via l' select2:selectévénement, la propriété supplémentaire vous permet également de rendre l'option légèrement différemment dans le résultat. Donc, si vous vouliez signaler visuellement le fait qu'il s'agit d'une nouvelle option en mettant " (nouveau) " à côté, vous pouvez faire quelque chose comme ça.

$("select").select2({
  tags: true,
  createTag: function (params) {
    return {
      id: params.term,
      text: params.term,
      newOption: true
    }
  },
  templateResult: function (data) {
    var $result = $("<span></span>");

    $result.text(data.text);

    if (data.newOption) {
      $result.append(" <em>(new)</em>");
    }

    return $result;
  }
});
Kevin Brown
la source
Cela a été très utile @ Markus1980Wien
abiieez
Je pense avoir utilisé cet extrait plusieurs fois.
Sahu V Kumar
Si cela ne fonctionne pas, vérifiez que vous avez ajouté cette option sur select2 pas ajouter dans les options ajax. pour select2 ajax
Zohaib
2
Son fonctionnement dans la version select2 (4.0.6) de cette manière: $ ("select"). Select2 ({tags: true, createTag: function (params) {return {id: params.term, text: params.term, newOption : true}}, templateResult: function (data) {var result = data.text; if (data.newOption) {result = result + '(new)';} return result;}}); merci @Kevin Brown
M. Salah
Cela devrait être la meilleure réponse. Cela fait un moment que je cherche cela, et cette option répond à toutes les questions que j'ai vues sur le sujet.
Justin
14

Juste pour garder le code en vie, je poste le code de @rrauenza Fiddle à partir de son commentaire .

HTML

<input type='hidden' id='tags' style='width:300px'/>

jQuery

$("#tags").select2({
    createSearchChoice:function(term, data) { 
        if ($(data).filter(function() { 
            return this.text.localeCompare(term)===0; 
        }).length===0) 
        {return {id:term, text:term};} 
    },
    multiple: false,
    data: [{id: 0, text: 'story'},{id: 1, text: 'bug'},{id: 2, text: 'task'}]
});
Michel Ayres
la source
2
Je suis allé au violon, mais cela ne semble pas fonctionner pour moi dans Chrome. Pouvez-vous confirmer?
IcedDante
@IcedDante le code fonctionne. le but dans le violon est juste de montrer comment cela doit être fait (la sélection est cachée dans le violon)
Michel Ayres
4
Quand je vais au violon, je ne vois nulle part une liste déroulante select2. Ne serait-il pas agréable d'avoir un exemple qui ... fait quelque chose?
IcedDante
Comment puis-je définir les données à partir d'une source externe? Je veux dire que faire si je veux charger des villes d'un pays sélectionné et que le pays sélectionné lui-même est un dropodown?
Ali Baig
12

Étant donné que beaucoup de ces réponses ne fonctionnent pas dans la version 4.0+, si vous utilisez ajax, vous pouvez demander au serveur d'ajouter la nouvelle valeur en option. Cela fonctionnerait donc comme ceci:

  1. L'utilisateur recherche une valeur (ce qui fait une requête ajax au serveur)
  2. Si la valeur est bonne, retournez l'option. Sinon, demandez au serveur d'ajouter cette option comme ceci:[{"text":" my NEW option)","id":"0"}]
  3. Lorsque le formulaire est soumis, vérifiez simplement si cette option est dans la base de données et sinon créez-la avant de l'enregistrer.
Eric
la source
6

Il y a une meilleure solution je pense maintenant

définir simplement le balisage sur vrai sur les options de sélection?

tags: true

sur https://select2.org/tagging

Steven Moffat
la source
4

Amélioration de la réponse @fmpwizard:

//Allow manually entered text in drop down.
createSearchChoice:function(term, data) {
  if ( $(data).filter( function() {
    return term.localeCompare(this.text)===0; //even if the this.text is undefined it works
  }).length===0) {
    return {id:term, text:term};
  }
},

//solution to this error: Uncaught TypeError: Cannot read property 'localeCompare' of undefined
Vikash Singh
la source
Je l'ai utilisé avec une légère modification, je vais mettre ma réponse dans une seconde mais merci.
Sam
1
var text = 'New York Mills';
var term = 'new york mills';
return text.localeCompare(term)===0;

Dans la plupart des cas, nous devons comparer les valeurs avec un registre insensible. Et ce code retournera false, ce qui conduira à la création d'enregistrements en double dans la base de données. De plus String.prototype.localeCompare () n'est pas pris en charge par le navigateur Safary et ce code ne fonctionnera pas dans ce navigateur;

return this.text.localeCompare(term)===0;

remplacera mieux à

return this.text.toLowerCase() === term.toLowerCase();
dépassé
la source
1

Merci pour l'aide, j'ai utilisé le code ci-dessous dans Codeigniter II et j'utilise la version: 3.5.2 de select2.

var results = [];
var location_url = <?php echo json_encode(site_url('job/location')); ?>;
$('.location_select').select2({
    ajax: {
        url: location_url,
        dataType: 'json',
        quietMillis: 100,
        data: function (term) {
            return {
                term: term
            };
        },
        results: function (data) {
            results = [];
            $.each(data, function(index, item){
                results.push({
                    id: item.location_id,
                    text: item.location_name
                });
            });
            return {
                results: results
            };
        }
    },
    //Allow manually entered text in drop down.
    createSearchChoice:function(term, results) {
        if ($(results).filter( function() {
            return term.localeCompare(this.text)===0; 
        }).length===0) {
            return {id:term, text:term + ' [New]'};
        }
    },
});
Sam
la source