Skip to content

Instantly share code, notes, and snippets.

@M-Yankov
Last active October 16, 2019 05:34
Show Gist options
  • Save M-Yankov/1451da29eddbd1bc71c0975af80e63ae to your computer and use it in GitHub Desktop.
Save M-Yankov/1451da29eddbd1bc71c0975af80e63ae to your computer and use it in GitHub Desktop.
select2 dropdown: When loading results with ajax, load them once. (the results are always the same)
var s2data = $allUnitsSelect.select2({
ajax: {
url: '/GetValues',
dataType: 'json',
data: function (params) {
var query = {
text: text,
}
return query;
},
processResults: function (responseValues) {
var listItems = mapResponseData(responseValues);
this.options.set('cacheDataSource', listItems);
return { results: listItems };
}
},
cacheDataSource: [],
allowClear: true,
placeholder: 'Select Values ...',
width: '100%',
}).data('select2');
s2data.dataAdapter.query = function (params, callback) {
var cacheDataSource = this.options.get('cacheDataSource');
if (cacheDataSource && cacheDataSource.length > 0) {
callback({ results: cacheDataSource });
}
else {
// call the original logic
var ajaxAdapterFunc = jQuery.fn.select2.amd.require('select2/data/ajax');
var ajaxAdapter = new ajaxAdapterFunc(this.$element, this.options);
ajaxAdapter.query(params, callback);
}
}
@wolgan09
Copy link

wolgan09 commented Oct 12, 2018

what if i want it to initialize select2 with the cached data on reload.
i want to set value from cached data instead of reading localstorage and set value comming from DB as selected value.
can you help me out.
Thanks in advance.
Code :

    element.select2({
        cacheDataSource: [],
        ajax: {
            url: url,
            dataType: 'json',
            data: function (params) {
                var query = {
                  page: params.page || 1
                }
            },
            processResults: function (data, params) {
                params.page = params.page || 1;
                //localStorage.setItem(dsName, JSON.stringify(data));         //store Cities in localstorage
                getSelect2DataSource(data, params, s2dataSource= [])
                s2dataSource.sort();
                this.options.set('cacheDataSource', s2dataSource)
                return {
                    results: s2dataSource || [],
                    pagination: {
                        more: (params.page * 100) < s2dataSource.length
                    }
                        
                    }
                }
            },
            cache: true,
            templateSelection: function (data) {
                if(!data.name && !data.title ){
                  return data.text;
                }
        }
    })

@M-Yankov
Copy link
Author

M-Yankov commented Nov 27, 2018

Woow! sorry that I'm responding too late (I've never received a notification), However I will check your issue and respond tonight with a solution.

@M-Yankov
Copy link
Author

I do not know exactly your case (context) The will be the same every time or the data needs to be fetched each type when the user focuses out of the search field. The example above is complex for specified version of select and it will load the results with ajax only the first time. If the page is reloaded the select2 dropdown needs to make another ajax to load the data (It was very specific in my case).
If you are not using any library/framework like angular, backbone, react, vue.js etc. then localStorage, sessionStorage and cookies are available as option to store data.
Otherwise you can use Server side to render the data along with HTML. And then when initialize select2 use something like:

   <select id="dropdown-select2">
        <option value="val1">Text 1</option>
        <option value="val2">Text 2</option>
        <option value="val3">Text 3</option>
       ....
   </select>

  <script>
     $("#dropdown-select2").select2();
</script>

Or you can load the data from storage when the page loads:

(function() {
  var cacheData = [];  // this is accessible only inside that function, not globally

   $(document).ready(function() {
      var cacheData = JSON.parse(window.localStorage.getItem('data'));
    }) ;

    function initializeDropdown(element) {
        element.select2({
              data: cacheData
              // other options
        });
    } 
})()

But the property cacheDataSource in my example always starts with empty array and it is per dropdown.
In short, you cannot use that property when you want to initialize select2's data.

@nj-git
Copy link

nj-git commented Oct 15, 2019

I had to update the code, else search stopped working

s2data.dataAdapter.query = function (params, callback) {
        var cacheDataSource = this.options.get('cacheDataSource');
        if (cacheDataSource && cacheDataSource.length > 0) {
            callback(
                {
                    results: cacheDataSource.filter(function (b) {return b.text && b.text.toLowerCase().includes(params.term.toLowerCase()); })
                });
        }
        else {
            var ajaxAdapterFunc = jQuery.fn.select2.amd.require('select2/data/ajax');
            var ajaxAdapter = new ajaxAdapterFunc(this.$element, this.options);
            ajaxAdapter.query(params, callback);
        }
    }

@M-Yankov
Copy link
Author

Hi @nj-git, nice catch.
After working with another dropdown libraries (in react) and hitting a lot of issues, be sure to handle the diacritics search. What I mean is when you have Français in the options and type Franc the search to return the options. I think this is enabled by default. Source

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment