¿Cómo usar Select2 con JSON a través de una solicitud Ajax?

88

Mi Select2 3.4.5 no funciona con datos JSON.

Aquí está mi cuadro de entrada en HTML:

<input class='form-control col-lg-5 itemSearch' type='text' placeholder='select item' />

... y mi JavaScript

$(".itemSearch").select2({
    placeholder: "Search for an Item",
    minimumInputLength: 2,
    ajax: {
        url: "/api/productSearch",
        dataType: 'json',
        quietMillis: 100,
        data: function (term, page) {
            return {
                option: term
            };
        },
        results: function (data, page) {
            var more = (page * 10) < data.total;
            return {
                results: data.itemName,
                more: more
            };
        }
    },
    formatResult: function (data, term) {
        return data;
    },
    formatSelection: function (data) {
        return data;
    },
    dropdownCssClass: "bigdrop",
    escapeMarkup: function (m) {
        return m;
    }
});

Hice una API con Laravel 4 que devuelve un valor cada vez que escribo algo en mi cuadro de texto.

Aquí está el resultado si escribo "prueba" en mi cuadro de texto:

[{"itemName":"Test item no. 1","id":5},
{"itemName":"Test item no. 2","id":6},
{"itemName":"Test item no. 3","id":7},
{"itemName":"Test item no. 4","id":8},
{"itemName":"Test item no. 5","id":9},
{"itemName":"Test item no. 6","id":10},
{"itemName":"Test item no. 7","id":11}]

No puedo agregar el resultado a mi menú desplegable Select2. Creo formatSelectiony estoy formatResultcausando el problema porque no sé qué parámetro debería colocarse en él. No sé dónde obtener esos parámetros como contenedor, objeto y consulta y los valores que debería devolver, o ¿mi respuesta JSON es incorrecta?

Melvnberd
fuente

Respuestas:

110

Aquí tienes un ejemplo

$("#profiles-thread").select2({
    minimumInputLength: 2,
    tags: [],
    ajax: {
        url: URL,
        dataType: 'json',
        type: "GET",
        quietMillis: 50,
        data: function (term) {
            return {
                term: term
            };
        },
        results: function (data) {
            return {
                results: $.map(data, function (item) {
                    return {
                        text: item.completeName,
                        slug: item.slug,
                        id: item.id
                    }
                })
            };
        }
    }
});

Es bastante facil

Tolo Palmer
fuente
2
Gracias por la sugerencia de $ .map
tacos_tacos_tacos
¿Puedes explicar el parámetro "slug"?
IcedDante
el elemento es un objeto con propiedades completeName, slug e id. Esto es solo un ejemplo, copia y pega.
Tolo Palmer
2
Slug es una propiedad real del artículo, su artículo, agregué esto ya que puede ver cómo agregar parámetros adicionales;)
Tolo Palmer
4
Recibo este error jquery.min.js: 2 Uncaught TypeError: No se puede leer la propiedad 'longitud' de nulo cuando mi servidor no devuelve ningún resultado.
Soptareanu Alex
109

para select2 v4.0.0 ligeramente diferente

$(".itemSearch").select2({
    tags: true,
    multiple: true,
    tokenSeparators: [',', ' '],
    minimumInputLength: 2,
    minimumResultsForSearch: 10,
    ajax: {
        url: URL,
        dataType: "json",
        type: "GET",
        data: function (params) {

            var queryParameters = {
                term: params.term
            }
            return queryParameters;
        },
        processResults: function (data) {
            return {
                results: $.map(data, function (item) {
                    return {
                        text: item.tag_value,
                        id: item.tag_id
                    }
                })
            };
        }
    }
});
pez navaja
fuente
8
No se puede hacer que esto funcione ... :( No se realizan llamadas al servidor.
Simanas
Funcionó gracias, el error que hice no fue adecuadamente mapeando a idy textvalores clave.
Ja8zyjits
18

En la versión 4.0.2 ligeramente diferente Just in processResultsy in result:

    processResults: function (data) {
        return {
            results: $.map(data.items, function (item) {
                return {
                    text: item.tag_value,
                    id: item.tag_id
                }
            })
        };
    }

Debe agregar data.itemsen result. itemses el nombre de Json:

{
  "items": [
    {"id": 1,"name": "Tetris","full_name": "s9xie/hed"},
    {"id": 2,"name": "Tetrisf","full_name": "s9xie/hed"}
  ]
}
Ebad ghafoory
fuente
1
Si elimino itemsde data.items, no necesitaría agregar un itemsatributo en la respuesta, ¿verdad? ;)
Yana Agun Siswanto
1
@bekicot sí, solo especifica $.map(data, function (item) si tu json es una matriz:[ {"id": 1,"text": "One"}, {"id": 2,"text": "Two"} ]
Tantowi Mustofa
2
He estado golpeando mi cabeza contra una pared y esto aclaró las cosas. Gracias, la documentación para select2 es muy deficiente.
Neil B.
11

Aquí les doy mi ejemplo que contiene -> Bandera del país, Ciudad, Estado, País.

Aquí está mi salida.

ingrese la descripción de la imagen aquí

Adjunte estos dos Cdn js o enlaces.

<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/js/select2.min.js"></script>

script js

//for apend flag of country.

function formatState (state) {
    console.log(state);
    if (!state.id) {
      return state.text;
    }
    var baseUrl = "admin/images/flags";
    var $state = $(
      '<span><img src="'+baseUrl+ '/' + state.contryflage.toLowerCase() + '.png"  class="img-flag" /> ' +state.text+ '</span>'
    );
    return $state;
  };


$(function(){
    $("#itemSearch").select2({
    minimumInputLength: 2,
    templateResult: formatState, //this is for append country flag.
    ajax: {
        url: URL,
        dataType: 'json',
        type: "POST",
        data: function (term) {
            return {
                term: term
            };
        },
        processResults: function (data) {
            return {
                results: $.map(data, function (item) {
                    return {
                        text: item.name+', '+item.state.name+', '+item.state.coutry.name,
                        id: item.id,
                        contryflage:item.state.coutry.sortname
                    }
                })
            };
        }

    }
});

Respuesta JSON esperada.

[
   {
      "id":7570,
      "name":"Brussels",
      "state":{
         "name":"Brabant",
         "coutry":{
            "sortname":"BE",
            "name":"Belgium",

         }
      }
   },
   {
      "id":7575,
      "name":"Brussels",
      "state":{
         "name":"Brabant Wallon",
         "coutry":{
            "sortname":"BE",
            "name":"Belgium",

         }
      }
   },
   {
      "id":7578,
      "name":"Brussel",
      "state":{
         "name":"Brussel",
         "coutry":{
            "sortname":"BE",
            "name":"Belgium",

         }
      }
   },

]
Dilip Hirapara
fuente
pero soy confuso en `data: function (term) {return {term: term}; }, `
Vikas Katariya
6

Así es como solucioné mi problema, obtengo datos en la variable de datos y al usar las soluciones anteriores recibí un error could not load results. Tuve que analizar los resultados de manera diferente en processResults.

searchBar.select2({
            ajax: {
                url: "/search/live/results/",
                dataType: 'json',
                headers : {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
                delay: 250,
                type: 'GET',
                data: function (params) {
                    return {
                        q: params.term, // search term
                    };
                },
                processResults: function (data) {
                    var arr = []
                    $.each(data, function (index, value) {
                        arr.push({
                            id: index,
                            text: value
                        })
                    })
                    return {
                        results: arr
                    };
                },
                cache: true
            },
            escapeMarkup: function (markup) { return markup; },
            minimumInputLength: 1
        });
Chaudhry Waqas
fuente
1

Los problemas pueden deberse a un mapeo incorrecto. ¿Está seguro de que tiene el resultado establecido en "datos"? En mi ejemplo, el código de backend devuelve resultados en la tecla "elementos", por lo que la asignación debería verse así:

results: $.map(data.items, function (item) {
....
}

y no:

 results: $.map(data, function (item) {
    ....
    }
ensayador
fuente
1

Mi ajax nunca se dispara hasta que envuelvo todo en

setTimeout(function(){ .... }, 3000);

Lo estaba usando en la sección montada de Vue. necesita más tiempo.

Apit John Ismail
fuente
0

Si la solicitud ajax no se activa, verifique la clase select2 en el elemento de selección. Eliminar la clase select2 solucionará ese problema.

sudin
fuente