Como usar Select2 com JSON via solicitação Ajax?

90

Meu Select2 3.4.5 não está funcionando com dados JSON.

Aqui está minha caixa de entrada em HTML:

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

… E meu 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;
    }
});

Fiz uma API com o Laravel 4 que retorna um valor sempre que digito algo na minha caixa de texto.

Este é o resultado se eu digitar "teste" na minha caixa 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}]

Não consigo adicionar o resultado à minha lista suspensa Select2. Eu penso formatSelectione formatResultestão causando o problema, porque eu não sei o parâmetro deve ser colocado sobre ele. Não sei onde obter esses parâmetros como container, objeto e consulta e os valores que ele deve retornar, ou minha resposta JSON está errada?

Melvnberd
fonte

Respostas:

111

Aqui você tem um exemplo

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

É bem facil

Tolo Palmer
fonte
2
Obrigado pela sugestão para $ .map
tacos_tacos_tacos
Você pode explicar o parâmetro "slug"?
IcedDante
item é um objeto com as propriedades completeName, slug e id. Este é apenas um exemplo, copie e cole.
Tolo Palmer
2
Slug é uma propriedade real do item, seu item, eu adicionei isso porque você pode ver como adicionar parâmetros extras;)
Tolo Palmer
4
Eu recebo este erro jquery.min.js: 2 TypeError não capturado: Não é possível ler a propriedade 'length' de null quando meu servidor não retorna nenhum resultado.
Soptareanu Alex de
109

para select2 v4.0.0 ligeiramente 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
                    }
                })
            };
        }
    }
});
peixe navalha
fonte
8
Não é possível fazer isso funcionar ... :( Nenhuma chamada sendo feita para o servidor.
Simanas
Funcionou, obrigado, o erro que cometi não foi mapear corretamente para ide textos valores-chave.
Ja8zyjits
18

Na versão 4.0.2 ligeiramente diferente Just in processResultse in result:

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

Você deve adicionar data.itemsno result. itemsé o nome Json:

{
  "items": [
    {"id": 1,"name": "Tetris","full_name": "s9xie/hed"},
    {"id": 2,"name": "Tetrisf","full_name": "s9xie/hed"}
  ]
}
Ebad ghafoory
fonte
1
Se eu remover itemsde data.itemseu não precisar adicionar itemsatributo no direito de resposta? ;)
Yana Agun Siswanto
1
@bekicot sim, você apenas especifica $.map(data, function (item) se seu json é uma matriz:[ {"id": 1,"text": "One"}, {"id": 2,"text": "Two"} ]
Tantowi Mustofa
2
Estive batendo minha cabeça contra uma parede e isso esclareceu as coisas. Obrigado, a documentação para select2 está faltando seriamente.
Neil B.
11

Aqui eu dou meu exemplo que contém -> Bandeira do país, cidade, estado, país.

Aqui está minha saída.

insira a descrição da imagem aqui

Anexe esses dois Cdn js ou links.

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

    }
});

Resposta 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
fonte
mas estou confuso em `data: function (term) {return {term: term}; }, `
Vikas Katariya
6

Foi assim que resolvi meu problema, estou obtendo dados na variável de dados e, usando as soluções acima, estou obtendo erros could not load results. Tive que analisar os resultados de maneira diferente em 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
fonte
1

Os problemas podem ser causados ​​por mapeamento incorreto. Tem certeza que tem seu resultado definido em "dados"? No meu exemplo, o código de back-end retorna resultados na chave "itens", então o mapeamento deve ser semelhante a:

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

e não:

 results: $.map(data, function (item) {
    ....
    }
testador
fonte
1

Meu ajax nunca é disparado até que eu envolva tudo em

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

Eu estava usando na seção montada do Vue. precisa de mais tempo.

Apit John Ismail
fonte
0

Se a solicitação ajax não for disparada, verifique a classe select2 no elemento select. Remover a classe select2 corrigirá esse problema.

Sudin
fonte