Seleccionar2 desplegable pero permitir nuevos valores por usuario?


125

Quiero tener un menú desplegable con un conjunto de valores, pero también permitir que el usuario "seleccione" un nuevo valor que no aparece allí.

Veo que select2 admite esto si lo está usando en tagsmodo, pero ¿hay alguna manera de hacerlo sin usar etiquetas?


1
Select2 nunca funcionó para mí, al menos createSearchChoice nunca funcionó para mí en 4.0.3, y no quería que mis usuarios esperaran que ajax se completara para devolver la misma palabra clave, así que tuve que implementar mi propia biblioteca, solo estoy compartirlo porque creo que podría ayudar a otros que todavía están confundidos como yo, por favor no rechace el
razzbee

Respuestas:


100

Para la versión 4+, verifique esta respuesta a continuación por Kevin Brown

En Select2 3.5.2 y versiones posteriores, puede usar algo como:

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

(tomado de una respuesta en la lista de correo select2, pero no puedo encontrar el enlace ahora)


44
Perdón por la respuesta tardía, pero muchas gracias por su solución. El otro póster, ¡publicó un enlace a tu esencia por cierto que te hace doblemente increíble! :)
johnjohn

rrauenza increíble, exactamente lo que estaba buscando
Matthias S

44
Agregar la selectOnBlur: truevoluntad hará el trabajo, consulte: stackoverflow.com/questions/25616520/…
Alireza Fattahi

1
Solo un aviso para futuros lectores, probablemente quieras usar tags: []junto con createSearchChoice.
Kevin Brown

55
El violín vinculado anteriormente parece roto.
Wolfr

175

La excelente respuesta proporcionada por @fmpwizard funciona para Select2 3.5.2 y posteriores, pero no funcionará en 4.0.0 .

Desde muy temprano (pero tal vez no tan temprano como esta pregunta), Select2 ha admitido "etiquetado": donde los usuarios pueden agregar su propio valor si se lo permite. Esto se puede habilitar a través de la tagsopción, y puede jugar con un ejemplo en la documentación .

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

Por defecto, esto creará una opción que tiene el mismo texto que el término de búsqueda que han ingresado. Puede modificar el objeto que se utiliza si desea marcarlo de una manera especial, o crear el objeto de forma remota una vez que se selecciona.

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

Además de servir como un indicador fácil de detectar en el objeto pasado a través del select2:selectevento, la propiedad adicional también le permite representar la opción de manera ligeramente diferente en el resultado. Entonces, si desea señalar visualmente el hecho de que es una nueva opción al poner " (nuevo) " al lado, puede hacer algo como esto.

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

Eso fue muy útil @ Markus1980Wien
abiieez

Creo que he usado este fragmento varias veces.
Sahu V Kumar

Si no funciona, verifique dos veces que haya agregado esta opción en select2, no agregue las opciones ajax. para select2 ajax
Zohaib

2
Su workign en la versión select2 (4.0.6) de esta manera: $ ("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;}}); gracias @Kevin Brown
M. Salah

Esta debería ser la mejor respuesta. He estado buscando durante un tiempo para esto, y esta opción responde a todas las preguntas que he visto sobre el tema.
Justin

14

Solo por mantener vivo el código, estoy publicando el código de @rrauenza Fiddle de su comentario .

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
Fui al violín, pero no parece estar funcionando para mí en Chrome. ¿Puedes confirmar?
IcedDante

@IcedDante el código está funcionando. el punto en el violín es solo mostrar cómo se debe hacer (la selección está oculta en el violín)
Michel Ayres

44
Cuando voy al violín, no veo un menú desplegable select2 en ninguna parte. ¿No sería bueno tener un ejemplo que en realidad ... haga algo?
IcedDante

¿Cómo puedo configurar los datos de una fuente externa? Quiero decir, ¿qué pasa si quiero cargar ciudades de un país seleccionado y el país seleccionado en sí mismo es un dropodown?
Ali Baig

12

Dado que muchas de estas respuestas no funcionan en 4.0+, si está utilizando ajax, puede hacer que el servidor agregue el nuevo valor como una opción. Entonces funcionaría así:

  1. El usuario busca valor (lo que hace una solicitud ajax al servidor)
  2. Si el valor se encuentra excelente, devuelva la opción. Si no, simplemente haga que el servidor agregue esa opción así:[{"text":" my NEW option)","id":"0"}]
  3. Cuando se envía el formulario, simplemente verifique si esa opción está en el DB y, si no, créelo antes de guardarlo.


4

Mejora en la respuesta de @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

Utilicé esto con una ligera modificación. Pondré mi respuesta en un segundo pero gracias.
Sam


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

En la mayoría de los casos, necesitamos comparar valores con un registro insensible. Y este código devolverá falso, lo que conducirá a la creación de registros duplicados en la base de datos. Además, String.prototype.localeCompare () no es compatible con el navegador Safary y este código no funcionará en este navegador;

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

reemplazará mejor a

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

1

Gracias por la ayuda chicos, usé el siguiente código dentro de Codeigniter II estoy usando la versión: 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]'};
        }
    },
});
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.