Seleziona2 menu a discesa ma consenti nuovi valori dall'utente?


125

Voglio avere un menu a discesa con una serie di valori, ma anche consentire all'utente di "selezionare" un nuovo valore non elencato lì.

Vedo che select2 lo supporta se lo stai usando in tagsmodalità, ma c'è un modo per farlo senza usare i tag?


1
Select2 non ha mai funzionato per me, almeno createSearchChoice non ha mai funzionato per me nella 4.0.3 e non volevo che i miei utenti aspettassero il completamento di ajax per restituire la stessa parola chiave, quindi ho dovuto implementare la mia libreria, sono solo condividendolo perché penso che potrebbe aiutare gli altri che sono ancora confusi come me, per favore non votare se non sei d'accordo con la mia risposta: github.com/razzbee/tagcomplete
razzbee

Risposte:


100

Per la versione 4+ controlla questa risposta di seguito da Kevin Brown

In Select2 3.5.2 e versioni precedenti, puoi usare qualcosa come:

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

(tratto da una risposta sulla mailing list select2, ma non riesco a trovare il link ora)


4
Ci scusiamo per la risposta in ritardo ma grazie mille per la tua soluzione! L'altro poster, ha pubblicato un collegamento alla tua sintesi che ti rende doppiamente fantastico! :)
johnjohn

rrauenza impressionante, esattamente quello che stavo cercando
Matthias S

4
Aggiunta la selectOnBlur: truefarà il lavoro si veda: stackoverflow.com/questions/25616520/...
Alireza Fattahi

1
Solo un avvertimento per i futuri lettori, che probabilmente vorrai usare tags: []insieme a createSearchChoice.
Kevin Brown

5
Il violino collegato sopra sembra rotto.
Wolfr

175

L' eccellente risposta fornita da @fmpwizard funziona per Select2 3.5.2 e versioni precedenti , ma non funzionerà in 4.0.0 .

Fin dall'inizio (ma forse non già a questa domanda), Select2 ha supportato il "tagging": dove gli utenti possono aggiungere il proprio valore se glielo permetti. Questo può essere abilitato tramite l' tagsopzione e puoi giocare con un esempio nella documentazione .

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

Per impostazione predefinita, questo creerà un'opzione che ha lo stesso testo del termine di ricerca che hanno inserito. È possibile modificare l'oggetto che viene utilizzato se si desidera contrassegnarlo in modo speciale o creare l'oggetto in remoto una volta selezionato.

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

Oltre a fungere da flag facile da individuare sull'oggetto passato attraverso l' select2:selectevento, la proprietà extra consente anche di rendere l'opzione leggermente diversa nel risultato. Quindi, se volessi segnalare visivamente il fatto che si tratta di una nuova opzione mettendo " (nuovo) " accanto ad essa, potresti fare qualcosa del genere.

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

È stato molto utile @ Markus1980Wien
abiieez

Penso di aver usato questo frammento più volte.
Sahu V Kumar

Se non funziona, ricontrolla di aver aggiunto questa opzione su select2 non aggiungere le opzioni ajax. per select2 ajax
Zohaib

2
Il suo workign nella versione select2 (4.0.6) in questo modo: $ ("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;}}); grazie @Kevin Brown
M. Salah

Questa dovrebbe essere la risposta migliore. Ho cercato per un po 'di tempo e questa opzione risponde a tutte le domande che ho visto sull'argomento.
Justin

14

Solo per mantenere vivo il codice, sto postando il codice di @rrauenza Fiddle dal suo commento .

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

2
Sono andato al violino, ma non sembra funzionare per me in Chrome. Puoi confermare?
IcedDante

@IcedDante il codice funziona. il punto nel violino è solo per mostrare come dovrebbe essere fatto (il selezionare è nascosto nel violino)
Michel Ayres

4
Quando vado al violino non vedo un menu a discesa select2 da nessuna parte. Non sarebbe bello avere un esempio che effettivamente ... fa qualcosa?
IcedDante

Come posso impostare i dati da una fonte esterna? Voglio dire, cosa succede se voglio caricare le città di un paese selezionato e il paese selezionato stesso è un menu a discesa?
Ali Baig

12

Poiché molte di queste risposte non funzionano in 4.0+, se stai usando ajax, potresti fare in modo che il server aggiunga il nuovo valore come opzione. Quindi funzionerebbe in questo modo:

  1. L'utente cerca il valore (che invia una richiesta ajax al server)
  2. Se il valore è ottimo, restituisci l'opzione. In caso contrario, chiedi al server di aggiungere quell'opzione in questo modo:[{"text":" my NEW option)","id":"0"}]
  3. Quando il modulo viene inviato, controlla se questa opzione è nel db e in caso contrario creala prima di salvare.


4

Miglioramento della risposta @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

L'ho usato con una leggera modifica, metterò la mia risposta in un secondo ma grazie.
Sam


1
var text = 'New York Mills';
var term = 'new york mills';
return text.localeCompare(term)===0;

Nella maggior parte dei casi è necessario confrontare i valori con il registro insensibile. E questo codice restituirà false, il che porterà alla creazione di record duplicati nel database. Inoltre String.prototype.localeCompare () non è supportato dal browser Safary e questo codice non funzionerà in questo browser;

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

sarà meglio sostituire a

return this.text.toLowerCase() === term.toLowerCase();

1

Grazie per l'aiuto ragazzi, ho usato il codice seguente all'interno di Codeigniter II sto usando la versione: 3.5.2 di 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]'};
        }
    },
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.