I'm using select2 jquery plugin with twitter bootstrap. It's working fine for smaller number of items. But when the list is huge (more than 1500 items) it really slows down. It's slowest in IE.
Normal Dropdownlist works very fast with more than 1500 items. Are there any workarounds for this situation?
You can make this work good even in IE8 with paginating the suggestions,
Code:
// Function to shuffle the demo data
function shuffle(str) {
return str
.split('')
.sort(function() {
return 0.5 - Math.random();
})
.join('');
}
// For demonstration purposes we first make
// a huge array of demo data (20 000 items)
// HEADS UP; for the _.map function i use underscore (actually lo-dash) here
function mockData() {
return _.map(_.range(1, 20000), function(i) {
return {
id: i,
text: shuffle('te ststr ing to shuffle') + ' ' + i,
};
});
}
(function() {
// init select 2
$('#test').select2({
data: mockData(),
placeholder: 'search',
multiple: true,
// query with pagination
query: function(q) {
var pageSize,
results,
that = this;
pageSize = 20; // or whatever pagesize
results = [];
if (q.term && q.term !== '') {
// HEADS UP; for the _.filter function i use underscore (actually lo-dash) here
results = _.filter(that.data, function(e) {
return e.text.toUpperCase().indexOf(q.term.toUpperCase()) >= 0;
});
} else if (q.term === '') {
results = that.data;
}
q.callback({
results: results.slice((q.page - 1) * pageSize, q.page * pageSize),
more: results.length >= q.page * pageSize,
});
},
});
})();
working example with 20000 items here: http://embed.plnkr.co/db8SXs/preview
plnkr embed does not support IE8 so try it out on IE8 with this link instead: http://run.plnkr.co/plunks/db8SXs/
I know it's an old question, but I wanted to share what worked for me. If you must pre-load the big list(depending on if you're starting from scratch or building on someone else's code, this may be easier), use the minimumInputLength
as described here in the documentation. The huge list of options doesn't show until the user has typed a couple of characters. This greatly reduces the performance hit while rendering them when the Select2 dropdown is actually selected. Hope that helps!
So keep in mind you are loading >1500 actual elements onto the page in the form of <option>
s, which can end up hurting page performance as well. As a user suggested in the a comment, you can solve the performance issue by making an AJAX call to a backend service that will return your values.
This is very old question and answer and even we have newer version of select2. but if someone is trying to search in optgroup too. can try this solution.
http://jsfiddle.net/na1zLkz3/4/
// Function to shuffle the demo data
var shuffle = function (str) {
return str.split('').sort(function () {
return 0.5 - Math.random();
}).join('');
};
// For demonstration purposes we first make
// a huge array of demo data (20 000 items)
// HEADS UP; for the _.map function i use underscore (actually lo-dash) here
var mockData = function () {
var array = _.map(_.range(1, 10), function (i) {
return {
id : i,
text: shuffle('te ststr ing to shuffle') + ' ' + i
};
});
return array;
};
var mockData1 = function () {
var array = _.map(_.range(10, 15), function (i) {
return {
id : i,
text: shuffle('te ststr ing to shuffle') + ' ' + i
};
});
return array;
};
var mockData2 = function () {
var array = _.map(_.range(15, 20), function (i) {
return {
id : i,
text: shuffle('te ststr ing to shuffle') + ' ' + i
};
});
return array;
};
// create demo data
var dummyData = mockData();
var dummyData1 = mockData1();
var dummyData2 = mockData2();
dummyData.push({
text: 'canada',
children: dummyData1
});
dummyData.push({
text: 'USA',
children: dummyData2
});
// init select 2
$('#ddlCar').select2({
data : dummyData,
// init selected from elements value
initSelection : function (element, callback) {
var initialData = [];
$(element.val().split(",")).each(function () {
initialData.push({
id : this,
text: this
});
});
callback(initialData);
},
// NOT NEEDED: These are just css for the demo data
dropdownCssClass : 'capitalize',
containerCssClass: 'capitalize',
// NOT NEEDED: text for loading more results
formatLoadMore : function() {return 'Loading more...'},
// query with pagination
query : function (q) {
var pageSize,
results;
pageSize = 20; // or whatever pagesize
var results = [];
if (q.term && q.term !== "") {
// HEADS UP; for the _.filter function i use underscore (actually lo-dash) here
var results = this.data;
var results = _.filter(results, function (e) {
if(typeof e.children != 'undefined')
{
subresults = _.filter(e.children, function (f) {
return (f.text.toUpperCase().indexOf(q.term.toUpperCase()) >= 0);
});
if(subresults.length > 0)
return true;
return false;
}
return (e.text.toUpperCase().indexOf(q.term.toUpperCase()) >= 0);
});
newresults = [];
for (var i = 0, len = results.length; i < len; i++) {
newresults[i] = {};
if(typeof results[i].text != 'undefined')
newresults[i].text = results[i].text;
if(typeof results[i].id != 'undefined')
newresults[i].id = results[i].id;
if(typeof results[i].children != 'undefined')
{
newresults[i].children = results[i].children;
newresults[i].children = _.filter(newresults[i].children, function (f) {
return (f.text.toUpperCase().indexOf(q.term.toUpperCase()) >= 0);
});
}
}
results = newresults;
} else if (q.term === "") {
results = this.data;
}
q.callback({
results: results.slice((q.page - 1) * pageSize, q.page * pageSize),
more : results.length >= q.page * pageSize
});
}
});
Here's a working version for Select2 v4
Based on the answer here: and modified it to make searching work with lo-dash
$(function () {
items = []
for (var i = 0; i < 1000; i++) {
items.push({ id: i, text : "item " + i})
}
pageSize = 50
jQuery.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) {
var results = [];
if (params.term && params.term !== '') {
results = _.filter(items, function(e) {
return e.text.toUpperCase().indexOf(params.term.toUpperCase()) >= 0;
});
} else {
results = items;
}
if (!("page" in params)) {
params.page = 1;
}
var data = {};
data.results = results.slice((params.page - 1) * pageSize, params.page * pageSize);
data.pagination = {};
data.pagination.more = params.page * pageSize < results.length;
callback(data);
};
$(document).ready(function () {
$("select").select2({
ajax: {},
dataAdapter: CustomData
});
});
})
});
JsFiddle: http://jsfiddle.net/nea053tw/
Edit: Fiddle changed.
The easiest works for me is:
$(".client_id").select2({
minimumInputLength: 2
});
You can change the value of minimumInputLength at your wish.
This way, select2 will not have to show whole list, rather it will bring result only after the fixed number of characters typed. Although you are still having the large array of list at front-end-code.
Also, if you are using allowClear, then you must declare placehodler like this:
$(".client_id").select2({
minimumInputLength: 2,
allowClear: true,
placeholder: '--Select Client--'
});
Check the documentation here http://select2.github.io/select2
来源:https://stackoverflow.com/questions/15041058/select2-performance-for-large-set-of-items