How to programmatically inject search queries into Select2 v4?

20,420

Solution 1

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.

Solution 2

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

Solution 3

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

Solution 4

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

Solution 5

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.

Share:
20,420
vgoklani
Author by

vgoklani

Updated on July 07, 2021

Comments

  • vgoklani
    vgoklani almost 3 years

    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
    vgoklani about 9 years
    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
    vgoklani about 9 years
    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
  • Kevin Brown-Silva
    Kevin Brown-Silva about 9 years
    @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).
  • vgoklani
    vgoklani about 9 years
    Yes I am using multiple select
  • Kevin Brown-Silva
    Kevin Brown-Silva about 9 years
    I've updated my answer to work for multiple selects as well, and included an example for them.
  • vgoklani
    vgoklani about 9 years
    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
    vgoklani about 9 years
    I added an image to show you precisely where I'm stuck. Thanks again for your help!
  • goyote
    goyote about 8 years
    This is not complete, how do you simulate an ENTER afterwards so the dropdown accepts the entered string and closes?
  • phazei
    phazei about 8 years
    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
  • user3057544
    user3057544 over 7 years
    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 ?
  • Johnner
    Johnner over 7 years
    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!
  • Santiago
    Santiago over 7 years
    I can simulate the ENTER with $('.select2-results__option[aria-selected]') .trigger("mouseup");
  • Faizan Anwer Ali Rupani
    Faizan Anwer Ali Rupani over 5 years
    Key Event triggers blocked by browser as of 2019 for security reason
  • mickmackusa
    mickmackusa about 3 years
    @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()?
  • dahe
    dahe about 2 years
    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.