How to use Select2 with JSON via Ajax request?
Asked Answered
T

8

106

My Select2 3.4.5 is not working with JSON data.

Here is my input box on HTML:

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

…and my 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;
    }
});

I made an API with Laravel 4 which returns a value whenever I type anything on my text box.

Here's the result if I type "test" on my text box:

[{"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}]

I can't add the result to my Select2 dropdown. I think formatSelection and formatResult are causing the problem because I don't know what parameter should be placed on it. I don't know where to get those parameters like container, object and query and the values it should be returning, or is my JSON response is wrong?

Terisateriyaki answered 4/1, 2014 at 21:2 Comment(0)
A
121

Here you have an example

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

It's quite easy

Asquint answered 6/2, 2014 at 11:52 Comment(7)
Can you explain the "slug" parameter?Acrosstheboard
item is object with completeName, slug and id properties. This is just an example, copy and paste.Asquint
From where you take "slug" param -? i can find only: itemName & idCispadane
Slug it is an actual property of item, your item, I added this as you can see how to add extra parameters ;)Asquint
I recive this error jquery.min.js:2 Uncaught TypeError: Cannot read property 'length' of null when my server return no result.Squeaky
It works for a single select box, but if I include two select boxes on the same page, only the last one loads. Is it normal behavior?Cranial
@Khalilullah is because the id of element is targeted (#profiles-thread) - and ids are unique in HTML document. You should probably target some css class etc,Juliettejulina
N
127

for select2 v4.0.0 slightly different

$(".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
                    }
                })
            };
        }
    }
});
Neckline answered 18/9, 2015 at 14:19 Comment(2)
Can't get this to work... :( No calls being made to server.Margy
It worked thanks, the mistake i made was not mapping properly to id and text key values.Savarin
A
121

Here you have an example

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

It's quite easy

Asquint answered 6/2, 2014 at 11:52 Comment(7)
Can you explain the "slug" parameter?Acrosstheboard
item is object with completeName, slug and id properties. This is just an example, copy and paste.Asquint
From where you take "slug" param -? i can find only: itemName & idCispadane
Slug it is an actual property of item, your item, I added this as you can see how to add extra parameters ;)Asquint
I recive this error jquery.min.js:2 Uncaught TypeError: Cannot read property 'length' of null when my server return no result.Squeaky
It works for a single select box, but if I include two select boxes on the same page, only the last one loads. Is it normal behavior?Cranial
@Khalilullah is because the id of element is targeted (#profiles-thread) - and ids are unique in HTML document. You should probably target some css class etc,Juliettejulina
U
24

Here I give you my example which contain --> Country flag, City, State, Country.

Here is my output.

enter image description here

Attach these two Cdn js or 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>

js script

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

    }
});

Expected JSON response.

[
   {
      "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",

         }
      }
   },

]
Unfounded answered 5/9, 2019 at 7:31 Comment(1)
but i m confusing in ` data: function (term) { return { term: term }; },`Foreigner
W
21

In Version 4.0.2 slightly different Just in processResults and in result :

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

You must add data.items in result. items is Json name :

{
  "items": [
    {"id": 1,"name": "Tetris","full_name": "s9xie/hed"},
    {"id": 2,"name": "Tetrisf","full_name": "s9xie/hed"}
  ]
}
Witenagemot answered 6/5, 2016 at 22:29 Comment(3)
If i remove items from data.items i wouldn't need to add items attribute on the response right ? ;)Knighton
@bekicot yes, you just only specify $.map(data, function (item) if your json is an array: [ {"id": 1,"text": "One"}, {"id": 2,"text": "Two"} ]Ralph
Have been bashing my head against a wall and this cleared things up. Thank you, the documentation for select2 is severely lacking.Mimesis
C
11

This is how I fixed my issue, I am getting data in data variable and by using above solutions I was getting error could not load results. I had to parse the results differently in 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
        });
Cantata answered 17/5, 2017 at 20:12 Comment(0)
H
4

My ajax never gets fired until I wrapped the whole thing in

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

I was using it in mounted section of Vue. it needs more time.

Horning answered 18/3, 2018 at 7:45 Comment(0)
A
2

Tthe problems may be caused by incorrect mapping. Are you sure you have your result set in "data"? In my example, the backend code returns results under "items" key, so the mapping should look like:

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

and not:

 results: $.map(data, function (item) {
    ....
    }
Amati answered 28/1, 2017 at 17:4 Comment(0)
C
1

If ajax request is not fired, please check the select2 class in the select element. Removing the select2 class will fix that issue.

Collis answered 9/9, 2018 at 5:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.