Sorting options elements alphabetically using jQuery

172,052

Solution 1

What I'd do is:

  1. Extract the text and value of each <option> into an array of objects;
  2. Sort the array;
  3. 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);
});

Here is a working jsfiddle.

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();
Share:
172,052
bomortensen
Author by

bomortensen

Updated on May 29, 2020

Comments

  • bomortensen
    bomortensen almost 4 years

    I'm trying to understand sorting option elements within a select 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
    Felix Kling almost 12 years
    $("#mSelect").append($options); should suffice :)
  • bomortensen
    bomortensen almost 12 years
    This did it for me! Just had to make all the > and < checks to upper case :-) Thanks a lot!!
  • Pointy
    Pointy almost 12 years
    Ah OK right, if you want to ignore alphabetic case then yes. Glad it worked!
  • Pointy
    Pointy almost 12 years
    The 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
    bomortensen almost 12 years
    yes, because JS weighs uppercase characters higher than lowercase when sorting.. so it seems ;-) Thanks again, works like a charm!
  • alexleonard
    alexleonard almost 11 years
    Thanks 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
    JayCrossler almost 10 years
    I went with the above, changed to: var at = $(a).text().toLowerCase(), bt = $(b).text().toLowerCase(); to make sorting case independent
  • user1261774
    user1261774 over 9 years
    I am new to jquery - where would I add the check for the upper case as mentioned by bomortensen?
  • Pointy
    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
    Vitor Almeida over 9 years
    Best answer. This is my case. I need to keep option data attrs
  • UdayKiran Pulipati
    UdayKiran Pulipati over 9 years
    Easy and simplified answer.
  • jbyrd
    jbyrd about 9 years
    In the last line, you can change sel.html('').append(opts_list) to simply sel.html(opts_list)
  • Jamie Barker
    Jamie Barker almost 9 years
    Here's the amended code to remember the currently selected option: jsfiddle.net/trELD/700
  • Cethy
    Cethy almost 9 years
    Should 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
    Julio Popócatl over 8 years
    Worked for me perfectly
  • Geoffrey Hale
    Geoffrey Hale over 8 years
    Seems to work without the get method. And how are you using that get without a key?
  • Pointy
    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
    Slay over 8 years
    may i know what is the meaning of passing a underscore in jquery .map() function
  • Alexander Derck
    Alexander Derck over 7 years
    Why not use value and text as propertynames? Your minimizer will get rid of it :). Great answer though, thanks
  • Kris Oye
    Kris Oye about 7 years
    This 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
    Greg Blass over 6 years
    This should be the selected answer! This is much simpler than above, and preserves any classes or data attributes.
  • Hughsie28
    Hughsie28 over 6 years
    Works for me perfectly as well.
  • Cristiano Maia
    Cristiano Maia over 5 years
    almost perfect, but Chrome and Firefox show the last option as selected.
  • Jeromy French
    Jeromy French almost 4 years
    I 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
    Mukesh Kumar over 3 years
    It'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
    Dr Fred over 2 years
    Thank you for this comment !
  • charlfields
    charlfields over 2 years
    To fix Chrome and Firefox last option selected, just keep track of the original value with this code at the beginning and end of this answervar original = $("#list").val(); //first line $("#list").val(original); //last line
  • Waqleh
    Waqleh over 2 years
    if you want to per perform case insensitive sorting do the following return $(a).text().toLowerCase() > $(b).text().toLowerCase() ? 1 : -1;