Select All of search result

Hi All,

is it possible to select all options of search result of multiple selection? In the screen shot below, I need to provide users with the possibility to select all options starting with ‘FC’.

image

Thanks a lot for your help in advance.
Özkan

Hi, Özkan—

Select2 doesn’t support a “select all” feature out of the box; however, you can write code to do it yourself. One way I can think of to do that is to use a custom sorter function . The sorter function receives an array of all the matching items, and should return an array with the items sorted in the order you want to display them in the dropdown.

In your case, you don’t need to change the order of the items, but you can insert another item at the beginning of the list of matched items, that says something like “Select all matches”. You also need to include the list of all the matching items’ IDs in the new item, so they are available for the next step.

The next step is to listen for the select2:select event, so when your “Select all” item is selected, you can programmatically replace that selection with the matched items.

I coded up the following demo:

  const addSelectAll = matches => {
    if (matches.length > 0) {
      // Insert a special "Select all matches" item at the start of the 
      // list of matched items.
      return [
        {id: 'selectAll', text: 'Select all matches', matchIds: matches.map(match => match.id)},
        ...matches
      ];
    }
  };

  const handleSelection = event => {
    if (event.params.data.id === 'selectAll') {
      $('#my-select').val(event.params.data.matchIds);
      $('#my-select').trigger('change');
    };
  };

  $('#my-select').select2({
    minimumInputLength: 2,
    multiple: true,
    sorter: addSelectAll,
    width: '15rem', // you might not need to specify this
  });
  $('#my-select').on('select2:select', handleSelection);

This works with hard-coded options (either in the HTML or the JavaScript), and I believe it would work with options retrieved via AJAX, although I can’t easily test this.

Note that I had to set a minimumInputLength, otherwise the addSelectAll callback receives all the items in the list when there is no input term, and it outputs the “Select all matches” item followed by all the items in the <select>. If you actually want to allow users to select all items, then you could omit the minimumInputLength configuration option. (In that case you might want to change the “select all” item’s text to something like “Select all items below”.)

Here are some screen shots showing how it works:
2019-10-04%2022_20_06-Select2%20select%20all%20matches

After choosing “Select all matches”:
2019-10-04%2022_20_51-Select2%20select%20all%20matches

Now I search for something else (“cd”):
2019-10-04%2022_21_30-Select2%20select%20all%20matches

Choosing “Select all matches” replaces the previous selections:
2019-10-04%2022_21_59-Select2%20select%20all%20matches

If you want to retain the current selections, then you’ll need to merge the current selections with the new ones in the handleSelection callback:

  const handleSelection = event => {
    if (event.params.data.id === 'selectAll') {
      curSelIds = $('#my-select').val() || [];
      $('#my-select').val([...curSelIds, ...event.params.data.matchIds]);
      $('#my-select').trigger('change');
    };
  };

2019-10-04%2022_45_40-Select2%20select%20all%20matches
2019-10-04%2022_46_17-Select2%20select%20all%20matches

I hope this helps you.

1 Like

Hi there,
I’ve found this jsfiddle Select2 select all/none - JSFiddle - Code Playground (which doesn’t work for me)
if you encounter the same problem, i’ve edited his code with the below:

/*
 Define the select all adapter in a way that it's reusable
 */

$.fn.select2.amd.define('select2/selectAllAdapter', [
    'select2/utils',
    'select2/dropdown',
    'select2/dropdown/attachBody'
], function (Utils, Dropdown, AttachBody) {

    function SelectAll() {}
    SelectAll.prototype.render = function (decorated) {
        var self = this,
                $rendered = decorated.call(this),
                $selectAll = $(
                        '<button class="btn btn-xs btn-default" type="button" style="margin-left:6px;"><i class="fa fa-check-square-o"></i> Select All</button>'
                        ),
                $unselectAll = $(
                        '<button class="btn btn-xs btn-default" type="button" style="margin-left:6px;"><i class="fa fa-square-o"></i> Unselect All</button>'
                        ),
                $btnContainer = $('<div style="margin-top:3px;">').append($selectAll).append($unselectAll);
        if (!this.$element.prop("multiple")) {
            // this isn't a multi-select -> don't add the buttons!
            return $rendered;
        }
        
        $rendered.find('.select2-dropdown').prepend($btnContainer);
        
        var $select2 = $(this.$element[0]);        
        $selectAll.on('click', function () {
            var vals = [];
            $select2.find('option').each(function () {
                vals.push(this.value);
            });
            $select2.val(vals); // Select the options with an array
            $select2.trigger('change'); // Notify any JS components that the value changed

        });
        $unselectAll.on('click', function (e) {
            $select2.val(null); // Select the option with null value
            $select2.trigger('change'); // Notify any JS components that the value change            
        });
        return $rendered;
    };

    return Utils.Decorate(
            Utils.Decorate(
                    Dropdown,
                    AttachBody
                    ),
            SelectAll
            );

});

make sure you have the select2.full.min.js release . otherwise the code won’t work as it uses AMD