33

I've built a web-app using a Select2 search box, which connects to our backend via AJAX. The search box passes the query (say "APPLES") to the backend, which then updates the page. How do I programmatically inject search queries into the search box? I need to pass in the "val" so that select2 calls the backend via AJAX and updates the page. I'm sure this is obvious, but I couldn't find it in the documentation.

For example, instead of forcing a user to type "APPLES" into the search box, I would like the user to click a button and have the word "APPLES" automatically populated into the search field, and then have the page update.

Thanks!


Following Kevin's comment, I'm not in this state where the text is embedded in the searchbox and the selector has picked the correct item. How do I submit (or trigger) this request, I tried "keydown", "pressdown", "submit", "click" (which clears the box), etc.

enter image description here

vgoklani
  • 10,685
  • 16
  • 63
  • 101
  • The bounty isn't possible, by the way, because there is no way to detect when the AJAX request that is triggered will finish without hooking into the global AJAX handler. – Kevin Brown-Silva Jun 10 '15 at 14:07
  • Just to confirm, there's no way to force the click-through? – vgoklani Jun 10 '15 at 14:10
  • Regardless, I'm grateful for all your help, and the bounty is yours. – vgoklani Jun 10 '15 at 14:11
  • 1
    You _can_ force the result to be selected by simulating the `mouseup` event (or just injecting the ` – Kevin Brown-Silva Jun 10 '15 at 14:23

7 Answers7

54

Select2 used to provide a select2('search', 'term') helper method that would have assisted with this, but it was not brought over to Select2 4.0.0.

There are a couple of ways that this could be done, but in general they all follow the same pattern of steps

  1. Open the Select2 dropdown
  2. Enter the search text into the search box
  3. Trigger the keyboard events necessary for Select2 to start searching (usually input)

So, right now, in Select2 4.0.0 the code to do that would look like

$('select').select2();

function select2_search ($el, term) {
  $el.select2('open');
  
  // Get the search box within the dropdown or the selection
  // Dropdown = single, Selection = multiple
  var $search = $el.data('select2').dropdown.$search || $el.data('select2').selection.$search;
  // This is undocumented and may change in the future
  
  $search.val(term);
  $search.trigger('keyup');
}

$('button').on('click', function () {
  var $select = $($(this).data('target'));
  select2_search($select, 'Arizona');
});
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.css" rel="stylesheet"/>

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.js"></script>

<select style="width: 200px;" id="single">
  <option value="AL">Alabama</option>
  <option value="AK">Alaska</option>
  <option value="AZ">Arizona</option>
</select>

<button type="button" data-target="#single">Search for 'Arizona'</button>
<br /><br />

<select style="width: 200px;" id="multiple" multiple="multiple">
  <option value="AL">Alabama</option>
  <option value="AK">Alaska</option>
  <option value="AZ">Arizona</option>
</select>

<button type="button" data-target="#multiple">Search for 'Arizona'</button>

While this example does not use AJAX, it will trigger an AJAX request if Select2 is configured for it.

Kevin Brown-Silva
  • 40,873
  • 40
  • 203
  • 237
  • Thanks for response Kevin. Unfortunately I don't see the $search variable after $e1.data('select2').dropdown. I'm also making an AJAX call, so select2 doesn't see all the ids until after the AJAX request. I've been working on this for a few days, hopefully you can clarify things. Thanks – vgoklani Jun 03 '15 at 14:18
  • I should add that I have two search boxes, and only one is using AJAX. The non-ajax select2 box handles injections seamlessly via $selectionBox.val(23).change('trigger'). I'm guessing that the AJAX version fails since it doesn't have the ids. when i run this function $selectionBoxAJAX.val(47).change('trigger'), an update gets pushed (the screen updates) but the query is empty, and the correct text does not get updated – vgoklani Jun 03 '15 at 14:24
  • @vgoklani I think the issue may be that you are using a multiple select, want to just confirm that (and I can update this answer to also support it). – Kevin Brown-Silva Jun 03 '15 at 16:18
  • Yes I am using multiple select – vgoklani Jun 03 '15 at 16:21
  • I've updated my answer to work for multiple selects as well, and included an example for them. – Kevin Brown-Silva Jun 03 '15 at 16:31
  • 1
    Thanks Kevin, it's almost there! The text is now in the selection box and is highlighted in the dropdown, what's the "trigger" to make it submit? – vgoklani Jun 03 '15 at 18:16
  • I added an image to show you precisely where I'm stuck. Thanks again for your help! – vgoklani Jun 03 '15 at 18:34
  • 3
    This is not complete, how do you simulate an ENTER afterwards so the dropdown accepts the entered string and closes? – goyote May 06 '16 at 01:45
  • So, the trigger('keyup') didn't do anything for me, I ended up using s2Obj.trigger('query', {term:term}); to trigger a search with the term I wanted – phazei Jun 17 '16 at 21:41
  • according to @goyote comment/question - "how do you simulate an ENTER afterwards so the dropdown accepts the entered string and closes" - was it answered somewhere ? – user3057544 Nov 23 '16 at 08:16
  • 4
    I can simulate the ENTER with $('.select2-results__option[aria-selected]') .trigger("mouseup"); – Santiago Feb 27 '17 at 23:13
  • @Kevin I am not a javascript SME, how does the trailing `$search` in `$search = $el.data('select2').dropdown.$search` work? How are you accessing `$search` before it is supplied? I don't follow this part. Can you [edit] the explanation into your answer? Is it your personal preference not to chain `val()` and `trigger()`? – mickmackusa Jun 07 '21 at 23:46
13

for me triggering 'keyup' only worked when the user didn't select any option yet. What works every time is to trigger 'input' instead. (only tested on Chrome)

so based on Kevin Brown's answer:

$('select').select2();

function select2_search ($el, term) {
  $el.select2('open');

  // Get the search box within the dropdown or the selection
  // Dropdown = single, Selection = multiple
  var $search = $el.data('select2').dropdown.$search || $el.data('select2').selection.$search;
  // This is undocumented and may change in the future

  $search.val(term);
  $search.trigger('input');
}

$('button').on('click', function () {
  var $select = $($(this).data('target'));
  select2_search($select, 'Arizona');
});
Marc A.
  • 411
  • 5
  • 5
8

The answers on this page got me almost there. And because others seem to have the same issues, I am sharing how I solved it.

Some of the comments on Kevin Browns answer asked how to simulate the ENTER after the text has been entered and is highlighted.

I managed to do that only with a timeout:

setTimeout(function() { $('.select2-results__option').trigger("mouseup"); }, 500);

So, the full solution would be this:

$('select').select2();

function select2_search ($el, term) {
  $el.select2('open');

  // Get the search box within the dropdown or the selection
  // Dropdown = single, Selection = multiple
  var $search = $el.data('select2').dropdown.$search || $el.data('select2').selection.$search;
  // This is undocumented and may change in the future

  $search.val(term);
  $search.trigger('input');
  setTimeout(function() { $('.select2-results__option').trigger("mouseup"); }, 500);

}

$('button').on('click', function () {
  var $select = $($(this).data('target'));
  select2_search($select, 'Arizona');
});
sunomad
  • 1,693
  • 18
  • 23
6

You can set minimumInputLength to 0 then in the data function you may check params.term length and if it's 0, set the filter value to your predefined search value.

It's quite silly, but it works ;)

Ivan Modric
  • 609
  • 6
  • 14
Edu
  • 61
  • 1
  • 1
  • 1
    This is what I was looking for! Thanks for "minimumInputLength: 0" suggestion. My task was to pre-populate select2 with some initial data with ajax call. So all I need to do is to set minimum input to 0 and to filter out request with empty GET param "q=" on the server and return default values. Awesome! – Johnner Jan 24 '17 at 22:51
  • Good solution, I am using a data attribute "no-minimum-input-length". If its present at .seelct2({ .. options .. }) initialization the minimumInputLength is set to 0. Resulting in search on click which is useful if there are just a handful of options to choose from loaded via ajax. – dahe May 24 '22 at 07:55
2

As an addition to this answer, we were trying to programmatically add a new 'tag' to a select2 configured for tagging. Instead of triggering a keyup event on the $search box, we had to do the following.

$search.val(tag);
$search.closest('.select2-search--inline')
    .trigger($.Event('input', { which: 13 }));
$search.closest('.select2-selection--multiple')
    .trigger($.Event('keydown', { which: 13 }));

This first fires an event that causes the 'search' module in select2 to add a 'highlighted' result containing the tag text, then the second event causes select2 to fire the 'select' event internally which adds a new tag to the select2 options and may also trigger other stuff, depending on how you've configured it.

skila
  • 69
  • 5
2

For those who is using Ajax call to populate select2 and want to search and set selected value.

There are other way you can you but this answer perfectly work for me with Select2 4.0.0

  • To strike set I used deley function

JS

$('.select2').select2();

    function select2_search_and_set(controlId, term) {
var control = $("#" + controlId);
var $search = control.data('select2').dropdown.$search || control.data('select2').selection.$search;

$search.val(term);
$search.trigger('keyup');

setTimeout(function () {
    $search.trigger($.Event('keydown', { which: 13 }));
}, 500);
}

   select2_search_and_set("target", 'term');

Html

<select class="form-control select2" id="target" name="target"></select>
1

I was driving nuts, until I came to this thread. I wanted to have a select2 dialogue where user can enter a name that may not one of the options but I can still set it and is visible.

With the help of a combinations of answer form here, I managed to solve my problem.

To do this:

  1. I first needed to set the tags option on select2 to true

  2. There was no need to open select2

  3. I needed to chnage the trigger from 'keyup' to 'input'

  4. I needed to add the following line at the end to simulate enter key $('.select2-results__option').trigger("mouseup");

     Here is the jsfiddle sample for you to try for yourself
    

    https://jsfiddle.net/jainpankaj/o8g37wfu/8/#&togetherjs=I0e96aNexC