73

Ok, I'm sure there's something simple set wrong here but I'm not 100% what it is.

So I am trying to use Select2 AJAX method as a way of users to search a database and select a result. The call itself is coming back with results, however it will not allow me to select the answer from the list. It also doesn't seem to allow you to "select" it on hover or up/ down arrow. So without further ado, here is my code:

index.html

<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
        <link rel="stylesheet" type="text/css" href="select2/select2.css" media="screen" />
        <script src="select2/select2.js"></script>
        <script src="select.js"></script>
    </head>
    <body>
        <input type="text" style="width: 500px" class="select2">
    </body>
</html>

select.js

jQuery(function() {

  var formatSelection = function(bond) {
    console.log(bond)
    return bond.name
  }

  var formatResult = function(bond) {
    return '<div class="select2-user-result">' + bond.name + '</div>'
  }

  var initSelection = function(elem, cb) {
    console.log(elem)
    return elem
  }

    $('.select2').select2({
      placeholder: "Policy Name",
      minimumInputLength: 3,
      multiple: false,
      quietMillis: 100,
      ajax: {
        url: "http://localhost:3000/search",
        dataType: 'json',
        type: 'POST',
        data: function(term, page) {
          return {
            search: term,
            page: page || 1
          }
        },
        results: function(bond, page) {
          return {results: bond.results, more: (bond.results && bond.results.length == 10 ? true: false)}
        }
      },
      formatResult: formatResult,
      formatSelection: formatSelection,
      initSelection: initSelection
    })
})

JSON Response

{
  error: null,
  results: [
    {
      name: 'Some Name',
      _id: 'Some Id'
    },
    {
      name: 'Some Name',
      _id: 'Some Id'
    }
  ]
}

Everything seems to pull in correctly, however I am unable to actually select the answer and have it input into the box. Is there a problem somewhere in my code?

AlbertEngelB
  • 16,016
  • 15
  • 66
  • 93
  • 2
    Upon further investigation, when I change the dropdown class from select2-result-unselectable to select2-result-selectable everything seems to work correctly. – AlbertEngelB Feb 11 '13 at 20:23
  • I'd avoid doing your jquery call with a class and use an id instead. $('#thisSelect').select2({...... – ganders Aug 15 '14 at 18:57
  • @ganders I don't know how that would matter at all. – AlbertEngelB Aug 15 '14 at 19:24
  • If you happen to be using 2 of these select2 implementations on the same form/page, then typing in one it would place the results in both. Classes are designed to be allowed for re-use, while ids should be single-purpose. – ganders Aug 15 '14 at 19:25

7 Answers7

140

After looking at another answer it would seem I need to also pass id field with every call, otherwise it will disable the input.

Sample code that fixed it:

$('.select2').select2({
  placeholder: "Policy Name",
  minimumInputLength: 3,
  multiple: false,
  quietMillis: 100,
  id: function(bond){ return bond._id; },
  ajax: {
    url: "http://localhost:3000/search",
    dataType: 'json',
    type: 'POST',
    data: function(term, page) {
      return {
        search: term,
        page: page || 1
      }
    },
    results: function(bond, page) {
      return {results: bond.results, more: (bond.results && bond.results.length == 10 ? true: false)}
    }
  },
  formatResult: formatResult,
  formatSelection: formatSelection,
  initSelection: initSelection
})

Edit

Since this keeps getting upvoted I'll elaborate a bit. The .select2() method expects a unique id field on all results. Thankfully, there's a workaround. The id option accepts a function like this:

function( <INDIVIDUAL_RESULT> ) {
  // Expects you to return a unique identifier.
  // Ideally this should be from the results of the $.ajax() call. 
}

Since my unique identifier was <RESULT>._id, I simply return <RESULT>._id;

Community
  • 1
  • 1
AlbertEngelB
  • 16,016
  • 15
  • 66
  • 93
  • 2
    Thank you so much for this answer! Huge, huge help! I was not getting any errors and everything I walked through indicated it should be working. – Mike Homol Mar 13 '14 at 18:54
  • @MikeHomol Not a problem, I'm glad this question helped so many people in the community. Surprised this is such a common issue! – AlbertEngelB Mar 13 '14 at 18:57
  • 1
    Thanks for this. Small note, when the form would be submitted, the fields value would be the string "object[Object]". Replaced "return {id: bond._id}" with "return bond._id" and everything is sunny again ... – medowlock May 15 '14 at 09:44
  • @BogdanG Ohhh, that is indeed correct. I didn't realize that I had it wrong in this answer. I'll update! – AlbertEngelB May 15 '14 at 18:31
  • @mlt This is very possible, I was using an almost two year old version at the time. If you reference a JSFiddle with a working example I will add it to the answer. – AlbertEngelB Oct 17 '14 at 18:26
  • 16
    This doesn't work in Select2 4.0 anymore unfortunately. You'll need the code [here](http://stackoverflow.com/a/29082217/1496552) to make it work. – awidgery Mar 26 '15 at 08:27
  • @awidgery Thanks for the info! I added the [tag:jquery-select2-3] tag to the question, hopefully that will narrow down what solution will work for you. – AlbertEngelB Mar 26 '15 at 15:46
15

The thing is that the JSON data need a property called "id". There's no need for

id: function(bond){ return bond._id; }

If the data does not have an id for itself, you can add it with a function on processResults like here.

        $(YOUR FIELD).select2({
            placeholder: "Start typing...",
            ajax: {
                type: "POST",
                contentType: "application/json; charset=utf-8",
                url: "YOUR API ENDPOINT",
                dataType: 'json',
                data: 
                    function (params) {
                        return JSON.stringify({ username: params.term });
                },
                processResults: function (data, page) {

                    var results = [];

                    $.each(JSON.parse(data.d), function (i, v) {
                        var o = {};
                        o.id = v.key;
                        o.name = v.displayName;
                        o.value = v.key;
                        results.push(o);
                    })

                    return {
                        results: results
                    };
                },
                cache: true
            },
            escapeMarkup: function (markup) { return markup;},
            minimumInputLength: 1,
            templateResult: function (people) {
                if (people.loading)
                    return people.text;

                var markup = '<option value="' + people.value + '">' + people.name + '</option>';

                return markup;
            },
            templateSelection: function (people) { return people.value || people.text }

        });    
Andres Gonzalez
  • 151
  • 1
  • 2
  • The ID option in select2 does not seem to work in the newer version, follow this solution if you are using the latest version as on May '16. – Vihari Piratla May 11 '16 at 14:11
7

Also be careful with the case. I was using Id but select2 expects id. Could save someone's time.

Eugene
  • 473
  • 1
  • 9
  • 15
6

Like Dropped.on.Caprica said: Every result item needs an unique id.

So just assign every result id an unique number:

$('#searchDriver').select2({
    ajax: {
       dataType: 'json',
       delay: 250,
       cache: true,
       url: '/users/search',
       processResults: function (data, params) {
           //data is an array of results
           data.forEach(function (d, i) {
               //Just assign a unique number or your own unique id
               d.id = i; // or e.id = e.userId;
           })

           return {
               results: data
           };
       },
    },
    escapeMarkup: function (markup) { return markup; },
    minimumInputLength: 1,
    templateResult: formatRepo,
    templateSelection: formatRepoSelection
});
Community
  • 1
  • 1
Anh Cao
  • 482
  • 7
  • 13
1

I have many problem regarding the following error Option 'ajax' is not allowed for Select2

In my case, appears for select when you are using select2 version 3.5, So you should upgrade to version 4.0 and you won't need hidden input attached to your select

Ebrahim
  • 1,740
  • 2
  • 25
  • 31
0

enter image description here

You can trigger selecting an option (in this case the first one) by opening the select2 element programmatically and then triggering a return keypress.

var e = jQuery.Event('keydown');
e.which = 13;

$('.offer_checkout_page_link select').select2('open');
$('.offer_checkout_page_link .select2-selection').trigger(e);

This will "set" the option as if you clicked on it. You can modify this to select a specific option by triggering the appropriate number of down keypresses before triggering the return one.

It seems as though under-the-hood when you click (or in this case hit enter) to select an option, an option element is added to the select element. You will notice that when the page first loads select2 select elements do not have any option element children. This is why other solutions suggest adding an option element using jQuery and then selecting it.

Justin Leveck
  • 2,308
  • 2
  • 20
  • 22
0

I was binding select2 to a div, somehow that won't work with ajax as dataSource so that might help someone.

<div id="testSelect2"> </div>

changed this to

<select id="testSelect2"> </select>

And it started keeping the selected item.

Mihir Dave
  • 3,954
  • 1
  • 12
  • 28