1

I have a huge json data source (over 50,000 + lines) loaded in memory from a static file.

Note: It's not important why I have it in a static file.

I use select2 (v 4.0.5) that initializes as:

function initSelect2(selectName, dataSelect) {
var pageSize = 20;

    $.fn.select2.amd.require(["select2/data/array", "select2/utils"],

        function (ArrayData, Utils) {
            function CustomData($element, options) {
                CustomData.__super__.constructor.call(this, $element, options);
            }
            Utils.Extend(CustomData, ArrayData);

            CustomData.prototype.query = function (params, callback) {
                if (!("page" in params)) {
                    params.page = 1;
                }

                var data = {};
                data.results = dataSelect.slice((params.page - 1) * pageSize, params.page * pageSize);
                data.pagination = {};
                data.pagination.more = params.page * pageSize < dataSelect.length;
                callback(data);
            };

            $('#mySelect3').select2({
                ajax: {},
                dataAdapter: CustomData,
                width: '100%'
            });
        }); 
}

I have one big problem. I can not set the value to select from jQuery. If I try like this:

$ ("#mySelect3").val(17003).trigger("change");

nothing will happen. But I think I'm doing it badly. If I understand the documentation I think I should implement function:

CustomData.prototype.current = function (callback) {}

that should create the data, and then function:

CustomData.prototype.query = function (params, callback) {}

should only filter them.

Can you please help me, how do I implement select2 initialization, that can work with many options and can by set from jQuery?

Puty
  • 100
  • 1
  • 13

2 Answers2

0

With custom data adapter you don't need pagination :


// create huge array 
function mockData() {
    var hugeArray = [];
    for (let i = 0; i < 50000; i++) {
        el = {
            id: i,
            text: 'My mock data ' + i,
        };
        hugeArray.push(el);
    }
    return hugeArray;
};

// define custom dataAdapter
$.fn.select2.amd.define("myCustomDataAdapter", 
    ['select2/data/array','select2/utils'], 
    function (ArrayData, Utils) {

        function CustomData ($element, options) {
            CustomData.__super__.constructor.call(this, $element, options);
        };

        Utils.Extend(CustomData, ArrayData);

        CustomData.prototype.query = function (params, callback) {

            var data = {
                // here replace mockData() by your array
                results: mockData()
            };

            callback(data);

        };

        return CustomData;

    }
);

//
$('#mySelect3').select2({
    allowClear: true,
    // use dataAdapter here
    dataAdapter:$.fn.select2.amd.require("myCustomDataAdapter"),
});

And with search you can do like this :


// create huge array 
function mockData() {
    var hugeArray = [];
    for (let i = 0; i < 50000; i++) {
        el = {
            id: i,
            text: 'My mock data ' + i,
        };
        hugeArray.push(el);
    }
    return hugeArray;
};

// define custom dataAdapter
$.fn.select2.amd.define("myCustomDataAdapter", 
    ['select2/data/array','select2/utils'], 
    function (ArrayData, Utils) {

        function CustomData ($element, options) {
            CustomData.__super__.constructor.call(this, $element, options);
        };

        Utils.Extend(CustomData, ArrayData);

        CustomData.prototype.query = function (params, callback) {

            var data = {
                // here replace mockData() by your array
                results: mockData()
            };

            if ($.trim(params.term) === '') {
                callback(data);

            } else {

                if (typeof data.results === 'undefined') {
                    return null;
                }

                var filteredResults = [];

                data.results.forEach(function (el) {
                    if (el.text.toUpperCase().indexOf(params.term.toUpperCase()) == 0) {
                        filteredResults.push(el);
                    }
                });

                if (filteredResults.length) {
                    var modifiedData = $.extend({}, data, true);
                    modifiedData.results = filteredResults;
                    callback(modifiedData);
                }

                return null;

            }
        };

        return CustomData;

    }
);

//
$('#mySelect3').select2({
    minimumInputLength: 2,
    tags: false,
    allowClear: true,
    // use dataAdapter here
    dataAdapter:$.fn.select2.amd.require("myCustomDataAdapter"),
});

simonbdbc
  • 1
  • 1
0

I had the same issue and this is how I solved it.

Note: We are using dataAdapter because we dealing with large that, so I am assuming your drop-down will contain large amount of data.

After implementing your DataAdapter with a query use this example to initialize your select2.

if(selectedValue !== null )
   {
      $("#item_value").select2({
         placeholder: 'Select an option',
         allowClear: true,
         disabled: false,
         formatLoadMore: 'Loading more...',
         ajax: {},
         data: [{ id: selectedValue, text: selectedValue }],
         dataAdapter: customData
      });

      $("#item_value").val(selectedValue).trigger('change');
   }else{
      $("#item_value").select2({
         placeholder: 'Select an option',
         allowClear: true,
         disabled: false,
         formatLoadMore: 'Loading more...',
         ajax: {},
         dataAdapter: customData
      });
   }

To set selected value in select2 you need to pass some data into data option, but as we are dealing with large amount of data. You can't pass the complete array of large data you have as it's going to cause your browser window to freeze and lead to a bad user performance. But instead set the data option only with the selected value you got from db or variable.

I hope this helps.

Gael Musi
  • 678
  • 1
  • 7
  • 20