How do I display the selected tags in Select2 below the dropdown box?

13,680

Solution 1

When your elements get rendered, a ul with a class is added for the elements. This class name is: select2-selection__rendered So my idea was that after it was rendered, I could take this class and add some bottom. For this I used JQuery using $(function() note that what this does is to load after everything has loaded, so for the javascript code you need, is as follows (tested):

Javascript code:

  <script>
  $(".js-example-tags").select2({
   tags: true
  });

   $(function() {
      //Here you add the bottom pixels you need. I added 200px.
      $('.select2-selection__rendered').css({top:'200px',position:'relative'});
   });
  </script>

Solution 2

I came across this question a few weeks ago and wanted to share an alternative solution that I felt carried less risk than some of the style modifications to Select2 that other answers required.

What our team ended up using was a script that listened to the change event of the underlying <select> element to build/rebuild a styled unordered list in a sibling element:

$(".js-example-tags").select2({
    tags: true
}).on('change', function() {
    var $selected = $(this).find('option:selected');
    var $container = $(this).siblings('.js-example-tags-container');

    var $list = $('<ul>');
    $selected.each(function(k, v) {
       var $li = $('<li class="tag-selected"><a class="destroy-tag-selected">×</a>' + $(v).text() + '</li>');
       $list.append($li);
    });
    $container.html('').append($list);
}).trigger('change');

And, to give the new list the functionality in addition to the appearance of the select2 tags, we listened for a click event and paired each list item with the corresponding option in the <select> so it could toggle the selected state and trigger the change event again:

$selected.each(function(k, v) {
    var $li = $('<li class="tag-selected"><a class="destroy-tag-selected">×</a>' + $(v).text() + '</li>');
    $li.children('a.destroy-tag-selected')
        .off('click.select2-copy')
        .on('click.select2-copy', function(e) {
              var $opt = $(this).data('select2-opt');
              $opt.attr('selected', false);
              $opt.parents('select').trigger('change');
        }).data('select2-opt', $(v));
    $list.append($li);
});

After this, it was a matter of using display: none to hide the .select2-selection__choice elements.

Note in jQuery version > 3 set property instead of attribute $opt.prop('selected', false) in other case it will not remove created tags;

The full example is available for review here: http://jsfiddle.net/tjnicolaides/ybneqdqa/ -- hope this helps someone else.

Solution 3

I had the same need, so I wrote a custom selection adapter that will work for Select2 v4.


What are Select2 Adapters?

According to docs, Select2 uses the Adapter pattern, so the recommended way to extend its functionality is by implementing our own adapters.

The SelectionAdapter controls the display of the selection option(s), as well anything else that needs to be embedded within the container, such as a search box.

Select2 provides the SingleSelection and MultipleSelection adapters as default implementations of the SelectionAdapter for single and multi-select controls, respectively.

The selection adapter can be overridden by assigning a custom adapter to the selectionAdapter configuration option.


Select2 with custom Selection Adapter

The full code of the plugin is too big to post it here. It has only 3kb minified. You have to include it after Select2 main javascript file:

<script src="select2.js"></script>
<script src="select2.customSelectionAdapter.min.js"></script>

And the css:

<link rel="stylesheet" href="select2.customSelectionAdapter.css" />

Then, initialise the plugin as follows:

var CustomSelectionAdapter = $.fn.select2.amd.require("select2/selection/customSelectionAdapter");

$("select").select2({
    // other options 
    selectionAdapter: CustomSelectionAdapter
});

By default, the tags are added immediately after the select2 container. You can use the selectionContainer option to add them somewhere else in the page:

$("select").select2({
    // other options 
    selectionAdapter: CustomSelectionAdapter,
    selectionContainer: $('.foo')
});

Demo

https://andreivictor.github.io/select2-customSelectionAdapter/

Share:
13,680

Related videos on Youtube

Mhluzi Bhaka
Author by

Mhluzi Bhaka

Trying to keep my head above the code!

Updated on September 16, 2022

Comments

  • Mhluzi Bhaka
    Mhluzi Bhaka almost 2 years

    I am using Select2 (version 4) with tags and would like to have the selected choices display below the input field.

    So instead of:

    Standard choices

    Rather have:

    enter image description here

    Is this possible and if so how do I achieve that?

    EDIT: Code is:

    <select class="js-example-tags form-control" multiple="multiple">
        <option selected="selected">orange</option>
        <option selected="selected">white</option>
        <option selected="selected">purple</option>
        <option selected="selected">red</option>
        <option selected="selected">blue</option>
        <option selected="selected">green</option>
    </select>
    

    and

    $(".js-example-tags").select2({
    tags: true
    })
    
  • Mhluzi Bhaka
    Mhluzi Bhaka about 9 years
    thank you, this is great and almost there for me..... one aspect on this is that if there are elements below the dropdown the display gets a bit confused with the selected tags being placed under the following elements. Is there a way to "auto-expand" the height of the added ul according to how many choices there are?
  • Mhluzi Bhaka
    Mhluzi Bhaka about 9 years
    I made a jsfiddle to demonstrate what I meant in the comment above: Basically I would like to be able to place the results under each relevant dropdown.
  • Herland Cid
    Herland Cid about 9 years
    is that better jsfiddle.net/q80ow33h/11 you can add the height you need. @MhluziBhaka Hold on. I didn't test the dropdown, not working properly
  • Mhluzi Bhaka
    Mhluzi Bhaka about 9 years
    You could try : $('#2 .select2-selection__rendered').css({top:'100px',position:'re‌​lative'}); $('#2 .select2-container').append("<div style='height:100px'></div>"); Have a look at this jsfiddle: jsfiddle.net/q80ow33h/12
  • Mhluzi Bhaka
    Mhluzi Bhaka about 9 years
    Just for clarity, in the answer above the #2 is the id of your specific select2
  • Denny
    Denny about 9 years
    The issue I was having was that if you select "multiple" the rendered Select2 isn't actually given an ID. I ended up having to use the .next() jQuery function and assume (yikes) that the select2 would always be the control right after the original select. Then i generated and set an ID on each Select2, based on the ID of the select. Raised an issue regarding it as well on the git: github.com/select2/select2/issues/3447
  • shorif2000
    shorif2000 over 8 years
    this is not correct, if you click in the text box , the cursor is not in the correct place
  • shorif2000
    shorif2000 over 8 years
    I have tried to apply this example but it is not working for me. can you please check. stackoverflow.com/questions/35626836/…
  • shorif2000
    shorif2000 over 8 years
  • RSmithlal
    RSmithlal almost 7 years
    You can give your selections container an additional class as per the docs, so you could target your css style to the select2 selections that are children of this specific class selector.
  • Janak Prajapati
    Janak Prajapati over 6 years
    The example works great If you see select container is completely blank what if i want to display place holder there?
  • Admin
    Admin over 6 years
    Thanks for this. I've tried to use this code with some alterations to styling, but removing (pressing "X") it actually has no effect. I believe this is because no ID is being set on each select option. codepen.io/ftahir192/pen/paeYzV This codepen demonstrates the problem. Wondering if anybody else has run into this issue and knows of a fix?