How to programmatically inject search queries into Select2 v4?
Asked Answered
R

7

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

Risinger answered 28/5, 2015 at 21:8 Comment(4)
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.Simulcast
Just to confirm, there's no way to force the click-through?Risinger
Regardless, I'm grateful for all your help, and the bounty is yours.Risinger
You can force the result to be selected by simulating the mouseup event (or just injecting the <option> if you have the information), but you can't predict (accurately) when the results list is going to display the result.Simulcast
S
56

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.

Simulcast answered 30/5, 2015 at 23:14 Comment(12)
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. ThanksRisinger
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 updatedRisinger
@Risinger 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).Simulcast
Yes I am using multiple selectRisinger
I've updated my answer to work for multiple selects as well, and included an example for them.Simulcast
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?Risinger
I added an image to show you precisely where I'm stuck. Thanks again for your help!Risinger
This is not complete, how do you simulate an ENTER afterwards so the dropdown accepts the entered string and closes?Merited
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 wantedVazquez
according to @Merited comment/question - "how do you simulate an ENTER afterwards so the dropdown accepts the entered string and closes" - was it answered somewhere ?Albuminoid
I can simulate the ENTER with $('.select2-results__option[aria-selected]') .trigger("mouseup");Tuberous
@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()?Convivial
E
15

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');
});
Endocarditis answered 9/2, 2017 at 20:6 Comment(2)
This should be the accepted answer or the accepted answer should be updatedCoition
Agree! this is what worked for meSiberson
T
10

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');
});
Taeniacide answered 7/4, 2018 at 13:45 Comment(0)
H
7

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

Heiskell answered 25/2, 2016 at 16:51 Comment(2)
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!Symptomatic
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.Demission
P
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.

Peltast answered 24/7, 2015 at 11:2 Comment(1)
Key Event triggers blocked by browser as of 2019 for security reasonProconsulate
C
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>
Culver answered 20/4, 2021 at 19:8 Comment(0)
B
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

Beheld answered 7/7, 2021 at 0:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.