Sorting options elements alphabetically using jQuery

JavascriptJqueryHtmlSorting

Javascript Problem Overview


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?

Javascript Solutions


Solution 1 - Javascript

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 - Javascript

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 - Javascript

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 - Javascript

<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 - Javascript

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();

Solution 6 - Javascript

Here's my improved version of Pointy's solution:

function sortSelectOptions(selector, skip_first) {
	var options = (skip_first) ? $(selector + ' option:not(:first)') : $(selector + ' option');
	var arr = options.map(function(_, o) { return { t: $(o).text(), v: o.value, s: $(o).prop('selected') }; }).get();
	arr.sort(function(o1, o2) {
	  var t1 = o1.t.toLowerCase(), t2 = o2.t.toLowerCase();
	  return t1 > t2 ? 1 : t1 < t2 ? -1 : 0;
	});	
	options.each(function(i, o) {
		o.value = arr[i].v;
		$(o).text(arr[i].t);
		if (arr[i].s) {
			$(o).attr('selected', 'selected').prop('selected', true);
		} else {
			$(o).removeAttr('selected');
			$(o).prop('selected', false);
		}
	});	
}

The function has the skip_first parameter, which is useful when you want to keep the first option on top, e.g. when it's "choose below:".

It also keeps track of the previously selected option.

Example usage:

jQuery(document).ready(function($) {
  
  sortSelectOptions('#select-id', true);

});

Solution 7 - Javascript

None of the answers worked for me. For some strange reason, when looping through the options, each option returns nothing when text() is called. Instead, I was forced to retrieve the option's label via attr('label')

/**
 * Sort the options of the target select list
 * alphabetically by label. For some reason, when
 * we call detach(), the returned options have no
 * text() and instead we're forced to get the option's
 * label via the 'label' attribute.
 * @param select jQuery selector
 */
function sort_multi_select(select) {
	var options = select.find('option');
	options.detach().sort(function (a, b) {
		var at = $(a).attr('label'), //label, not text()
			bt = $(b).attr('label');
		return at > bt ? 1 : at < bt ? -1 : 0;
	});
	options.appendTo(select);
}

//example
sort_multi_select($('#my_select'));

Solution 8 - Javascript

I combined parts from marxin's and kuxa's excellent answers to create a jQuery custom function that

  1. sorts the options by their text values (case-insensitive),

  2. maintains any already-selected value, and

  3. returns the original jQuery objects against which the function is executed:

    $.fn.extend({
    	sortSelect() {
    		return this.each(function(){
    			let $this = $(this),
    				original_selection = $this.val(),
    				$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);
    			});
    			
    			$this.val(original_selection); 
    		})
    	}
    });
    

Working example on jsFiddle is available at https://jsfiddle.net/jhfrench/64och25e/.

Solution 9 - Javascript

The jquery.selectboxes.js plugin has a sort method. You can implement the plugin, or dive into the code to see a way to sort the options.

Solution 10 - Javascript

Yes you can sort the options by its text and append it back to the select box.

 function NASort(a, b) {    
      if (a.innerHTML == 'NA') {
          return 1;   
      }
      else if (b.innerHTML == 'NA') {
          return -1;   
      }       
      return (a.innerHTML > b.innerHTML) ? 1 : -1;
  };

Fiddle: https://jsfiddle.net/vaishali_ravisankar/5zfohf6v/

Solution 11 - Javascript

Malakgeorge answer is nice an can be easily wrapped into a jQuery function:

$.fn.sortSelectByText = function(){
	this.each(function(){
		var selected = $(this).val(); 
		var opts_list = $(this).find('option');
		opts_list.sort(function(a, b) { return $(a).text() > $(b).text() ? 1 : -1; });
		$(this).html('').append(opts_list);
		$(this).val(selected); 
	})
	return this;		
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbomortensenView Question on Stackoverflow
Solution 1 - JavascriptPointyView Answer on Stackoverflow
Solution 2 - JavascriptmarxinView Answer on Stackoverflow
Solution 3 - JavascriptGerbusView Answer on Stackoverflow
Solution 4 - JavascriptDiodeView Answer on Stackoverflow
Solution 5 - JavascriptKuxaView Answer on Stackoverflow
Solution 6 - JavascriptVictor BVView Answer on Stackoverflow
Solution 7 - JavascriptrmirabelleView Answer on Stackoverflow
Solution 8 - JavascriptJeromy FrenchView Answer on Stackoverflow
Solution 9 - JavascriptSam TysonView Answer on Stackoverflow
Solution 10 - Javascriptshali raviView Answer on Stackoverflow
Solution 11 - JavascriptDr FredView Answer on Stackoverflow