Sorting options elements alphabetically using jQuery
Solution 1
What I'd do is:
- Extract the text and value of each
<option>
into an array of objects; - Sort the array;
- Update the
<option>
elements with the array contents in order.
To do that with jQuery, you could do this:
var options = $('select.whatever option');
var arr = options.map(function(_, o) { return { t: $(o).text(), v: o.value }; }).get();
arr.sort(function(o1, o2) { return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0; });
options.each(function(i, o) {
o.value = arr[i].v;
$(o).text(arr[i].t);
});
edit — If you want to sort such that you ignore alphabetic case, you can use the JavaScript .toUpperCase()
or .toLowerCase()
functions before comparing:
arr.sort(function(o1, o2) {
var t1 = o1.t.toLowerCase(), t2 = o2.t.toLowerCase();
return t1 > t2 ? 1 : t1 < t2 ? -1 : 0;
});
Solution 2
Accepted answer is not the best in all cases because sometimes you want to perserve classes of options and different arguments (for example data-foo).
My solution is:
var sel = $('#select_id');
var selected = sel.val(); // cache selected value, before reordering
var opts_list = sel.find('option');
opts_list.sort(function(a, b) { return $(a).text() > $(b).text() ? 1 : -1; });
sel.html('').append(opts_list);
sel.val(selected); // set cached selected value
//For ie11 or those who get a blank options, replace html('') empty()
Solution 3
html:
<select id="list">
<option value="op3">option 3</option>
<option value="op1">option 1</option>
<option value="op2">option 2</option>
</select>
jQuery:
var options = $("#list option"); // Collect options
options.detach().sort(function(a,b) { // Detach from select, then Sort
var at = $(a).text();
var bt = $(b).text();
return (at > bt)?1:((at < bt)?-1:0); // Tell the sort function how to order
});
options.appendTo("#list"); // Re-attach to select
I used tracevipin's solution, which worked fantastically. I provide a slightly modified version here for anyone like me who likes to find easily readable code, and compress it after it's understood. I've also used .detach
instead of .remove
to preserve any bindings on the option DOM elements.
Solution 4
<select id="mSelect" >
<option value="val1" > DEF </option>
<option value="val4" > GRT </option>
<option value="val2" > ABC </option>
<option value="val3" > OPL </option>
<option value="val5" > AWS </option>
<option value="val9" > BTY </option>
</select>
.
$("#mSelect").append($("#mSelect option").remove().sort(function(a, b) {
var at = $(a).text(), bt = $(b).text();
return (at > bt)?1:((at < bt)?-1:0);
}));
Solution 5
I know this topic is old but I think my answer can be useful for a lot of people.
Here is jQuery plugin made from Pointy's answer using ES6:
/**
* Sort values alphabetically in select
* source: http://stackoverflow.com/questions/12073270/sorting-options-elements-alphabetically-using-jquery
*/
$.fn.extend({
sortSelect() {
let options = this.find("option"),
arr = options.map(function(_, o) { return { t: $(o).text(), v: o.value }; }).get();
arr.sort((o1, o2) => { // sort select
let t1 = o1.t.toLowerCase(),
t2 = o2.t.toLowerCase();
return t1 > t2 ? 1 : t1 < t2 ? -1 : 0;
});
options.each((i, o) => {
o.value = arr[i].v;
$(o).text(arr[i].t);
});
}
});
Use is very easy
$("select").sortSelect();
bomortensen
Updated on May 29, 2020Comments
-
bomortensen almost 4 years
I'm trying to understand sorting
option
elements within aselect
element alphabetically. Ideally, I'd like to have this as a separate function where I can just pass in the select element since it needs to be sorted when the user clicks some buttons.I've searched high and low for a good way of doing this, but haven't been able to find anything that worked for me.
The option elements should be sorted alphabetically by text, not value.
Is this possible in some way?
-
Felix Kling almost 12 years
$("#mSelect").append($options);
should suffice :) -
bomortensen almost 12 yearsThis did it for me! Just had to make all the > and < checks to upper case :-) Thanks a lot!!
-
Pointy almost 12 yearsAh OK right, if you want to ignore alphabetic case then yes. Glad it worked!
-
Pointy almost 12 yearsThe callback to
.sort()
should return a number that's less than zero, zero, or greater, to reflect the ordering relationship. Returning a boolean won't really work right I don't think. -
bomortensen almost 12 yearsyes, because JS weighs uppercase characters higher than lowercase when sorting.. so it seems ;-) Thanks again, works like a charm!
-
alexleonard almost 11 yearsThanks for this answer - solved my problem almost entirely. I just needed to augment it to account for tracking the selected option. For the arr options.map I added "s: $(o).attr('selected')", and then in options.each just needed to add: $(o).attr('selected', arr[i].s); Thanks!
-
JayCrossler almost 10 yearsI went with the above, changed to: var at = $(a).text().toLowerCase(), bt = $(b).text().toLowerCase(); to make sorting case independent
-
user1261774 over 9 yearsI am new to jquery - where would I add the check for the upper case as mentioned by bomortensen?
-
Pointy over 9 years@user1261774 if you want to sort without regard to alphabetic case, you can use some functions to convert the strings. I'll extend the answer.
-
Vitor Almeida over 9 yearsBest answer. This is my case. I need to keep option data attrs
-
UdayKiran Pulipati over 9 yearsEasy and simplified answer.
-
jbyrd about 9 yearsIn the last line, you can change sel.html('').append(opts_list) to simply sel.html(opts_list)
-
Jamie Barker almost 9 yearsHere's the amended code to remember the currently selected option: jsfiddle.net/trELD/700
-
Cethy almost 9 yearsShould be noted that it does not work in ie(11) : the options lose their labels. The most cross-browser solution I found is a jquery-less one.
-
Julio Popócatl over 8 yearsWorked for me perfectly
-
Geoffrey Hale over 8 yearsSeems to work without the get method. And how are you using that get without a key?
-
Pointy over 8 years@GeoffreyHale it probably does work without
.get()
; the jQuery object more-or-less mimics an array. When you call.get()
with no key, you get back a real array containing the DOM elements. -
Slay over 8 yearsmay i know what is the meaning of passing a underscore in jquery .map() function
-
Alexander Derck over 7 yearsWhy not use
value
andtext
as propertynames? Your minimizer will get rid of it :). Great answer though, thanks -
Kris Oye about 7 yearsThis is the best solution IMO and very similar to what I was going to post since it preserves the state of the elements (even for multiple selections).
-
Greg Blass over 6 yearsThis should be the selected answer! This is much simpler than above, and preserves any classes or data attributes.
-
Hughsie28 over 6 yearsWorks for me perfectly as well.
-
Cristiano Maia over 5 yearsalmost perfect, but Chrome and Firefox show the last option as selected.
-
Jeromy French almost 4 yearsI love that I could use some of the time this Q/A saved me by enhancing the answers in a way that hopefully benefits someone else. Viva Stack Overflow!!!
-
Mukesh Kumar over 3 yearsIt's a good solution but it doesn't work in IE11. When I applied this function to the dropdown list, the options' text gets empty. If you replace .html('') with .empty(), it should work.
-
Dr Fred over 2 yearsThank you for this comment !
-
charlfields over 2 yearsTo fix Chrome and Firefox last option selected, just keep track of the original value with this code at the beginning and end of this answer
var original = $("#list").val(); //first line $("#list").val(original); //last line
-
Waqleh over 2 yearsif you want to per perform case insensitive sorting do the following
return $(a).text().toLowerCase() > $(b).text().toLowerCase() ? 1 : -1;