107

I have a <select> element with the multiple attribute. How can I get this element's selected values using JavaScript?

Here's what I'm trying:

function loopSelected() { 
    var txtSelectedValuesObj = document.getElementById('txtSelectedValues');
    var selectedArray = new Array();
    var selObj = document.getElementById('slct'); 
    var i;
    var count = 0;
    for (i=0; i<selObj.options.length; i++) { 
        if (selObj.options[i].selected) {
            selectedArray[count] = selObj.options[i].value;
            count++; 
        } 
    } 
    txtSelectedValuesObj.value = selectedArray;
}
2
  • Do you have any code written? With that would be easy to help :)
    – Nobita
    May 3, 2011 at 7:08
  • Most questions are outdated, here is the shortest path nowadays: stackoverflow.com/a/73949951
    – Basj
    Oct 4, 2022 at 16:30

28 Answers 28

147

No jQuery:

// Return an array of the selected opion values
// select is an HTML select element
function getSelectValues(select) {
  var result = [];
  var options = select && select.options;
  var opt;

  for (var i=0, iLen=options.length; i<iLen; i++) {
    opt = options[i];

    if (opt.selected) {
      result.push(opt.value || opt.text);
    }
  }
  return result;
}

Quick example:

<select multiple>
  <option>opt 1 text
  <option value="opt 2 value">opt 2 text
</select>
<button onclick="
  var el = document.getElementsByTagName('select')[0];
  alert(getSelectValues(el));
">Show selected values</button>
4
  • 2
    Thank you for this answer. Could you please step through it for me? I think I understand MOST of it, but what does var options = select && select.options; do? In my inexperience, I expected that to be var options = select.options;
    – TecBrat
    Jan 22, 2014 at 20:13
  • 13
    select is not the best variable name in JavaScript.
    – VisioN
    Mar 5, 2014 at 11:12
  • 6
    @TecBrat var options = select && select.options ensures that select is not undefined, before accessing its attributes.
    – Qwerty
    Aug 11, 2015 at 11:23
  • 1
    I don't think the line with && makes much sense ... if selectis not defined getElementByIdwill return null. In this case, options will be null and error once you try to access to length property. But maybe I'm missing something?
    – Xen_mar
    Aug 28, 2020 at 18:31
134

With jQuery, the usual way:

var values = $('#select-meal-type').val();

From the docs:

In the case of <select multiple="multiple"> elements, the .val() method returns an array containing each selected option;

1
  • 1
    This is perfect. Is there also a way to retrieve the labels or text instead of the values themselves?
    – Cos
    Nov 26, 2022 at 23:57
79

Actually, I found the best, most-succinct, fastest, and most-compatible way using pure JavaScript (assuming you don't need to fully support IE lte 8) is the following:

var values = Array.prototype.slice.call(document.querySelectorAll('#select-meal-type option:checked'),0).map(function(v,i,a) { 
    return v.value; 
});

UPDATE (2017-02-14):

An even more succinct way using ES6/ES2015 (for the browsers that support it):

const selected = document.querySelectorAll('#select-meal-type option:checked');
const values = Array.from(selected).map(el => el.value);
6
  • 16
    Alternatively, if you have the element: Array.from(element.querySelectorAll("option:checked"),e=>e.value); Apr 11, 2018 at 4:37
  • 2
    Just FYI, it is faster to use the selectedOptions/options collection than to use querySelectorAll. Nov 7, 2018 at 19:47
  • 7
    Thanks @AdamLeggett. For reference to those who don't know, that would change make @Someguynamedpie's code above to: Array.from(element.selectedOptions).map(v=>v.value);.
    – KyleFarris
    Nov 8, 2018 at 20:45
  • It would, but see my answer below - it doesn't work at all on IE and has odd behavior in some older versions of Chrome and Firefox. If you don't care about performance, querySelectorAll or filtering element.options does get the job done. Also, you can do [].map.call() instead of using Array.from(), I don't know what impact this would have on performance but it certainly wouldn't be negative. Nov 8, 2018 at 21:09
  • used checked This worked for me, on a multi select dropdown, but should work for all drop-downs as well $(".multiple_select > option:checked").each(function(){ console.log(this.value) }); Aug 29, 2019 at 13:48
74

You can use selectedOptions property

var options = document.getElementById('select-meal-type').selectedOptions;
var values = Array.from(options).map(({ value }) => value);
console.log(values);
<select id="select-meal-type" multiple="multiple">
    <option value="1">Breakfast</option>
    <option value="2" selected>Lunch</option>
    <option value="3">Dinner</option>
    <option value="4" selected>Snacks</option>
    <option value="5">Dessert</option>
</select>

5
  • 7
    A native, no-fuss, non-jQuery answer. Thank you. Feb 22, 2021 at 16:32
  • 2
    this is a fantastic answer super simple and concise and can even be reduced to a single line let selectedOptions = Array.from(document.getElementById(selectElem).selectedOptions).map(({ value }) => value);
    – d0rf47
    Jan 25, 2022 at 22:15
  • this works if the selected is in the options tag but did not work if changes on the form Apr 9, 2022 at 7:00
  • 1
    In 2023 this should be the accepted answer. Much cleaner and cross-compatible. Does not require jQuery or other convoluted steps. Jan 30, 2023 at 19:08
  • Thank you. .selectedOptions was not mentioned in the <select> docs but is in HTMLSelectElement Dec 26, 2023 at 7:06
45

ES6

[...select.options].filter(option => option.selected).map(option => option.value)

Where select is a reference to the <select> element.

To break it down:

  • [...select.options] takes the Array-like list of options and destructures it so that we can use Array.prototype methods on it (Edit: also consider using Array.from())
  • filter(...) reduces the options to only the ones that are selected
  • map(...) converts the raw <option> elements into their respective values
6
  • 5
    Nice functional implementation :)
    – roadev
    Nov 22, 2016 at 14:27
  • You could use just reduce() method My implementation
    – To_wave
    Jun 15, 2017 at 19:00
  • 2
    @Evgeny many ways to solve it. You should post your approach in a new answer. Jul 31, 2017 at 21:41
  • 1
    This code looks much nicer than the ugly for loop over options.length. But is [...select.options] efficient in modern JS? Doesn't this iterate over whole collection three times? (i.e. first to build an array from options, second to filter, third to map) where you could do it in one go with ugly for loop
    – Anentropic
    Dec 6, 2017 at 17:11
  • 2
    @Anentropic it's a good question but I don't think efficiency matters much unless we're talking about hundreds or thousands of options. Apr 30, 2018 at 0:20
42

If you wanna go the modern way, you can do this:

const selectedOpts = [...field.options].filter(x => x.selected);

The ... operator maps iterable (HTMLOptionsCollection) to the array.

If you're just interested in the values, you can add a map() call:

const selectedValues = [...field.options]
                     .filter(x => x.selected)
                     .map(x => x.value);
0
28

Check-it Out:

HTML:

<a id="aSelect" href="#">Select</a>
<br />
<asp:ListBox ID="lstSelect" runat="server"  SelectionMode="Multiple" Width="100px">
    <asp:ListItem Text="Raj" Value="1"></asp:ListItem>
    <asp:ListItem Text="Karan" Value="2"></asp:ListItem>
    <asp:ListItem Text="Riya" Value="3"></asp:ListItem>
    <asp:ListItem Text="Aman" Value="4"></asp:ListItem>
    <asp:ListItem Text="Tom" Value="5"></asp:ListItem>
</asp:ListBox>

JQUERY:

$("#aSelect").click(function(){
    var selectedValues = [];    
    $("#lstSelect :selected").each(function(){
        selectedValues.push($(this).val()); 
    });
    alert(selectedValues);
    return false;
});

CLICK HERE TO SEE THE DEMO

1
  • 3
    Not a fan - the "HTML" isn't HTML (readable, but not HTML), and the answer requires adding JQuery as a dependency.
    – Iiridayn
    Dec 29, 2017 at 23:55
18

First, use Array.from to convert the HTMLCollection object to an array.

let selectElement = document.getElementById('categorySelect')
let selectedValues = Array.from(selectElement.selectedOptions)
        .map(option => option.value) // make sure you know what '.map' does

// you could also do: selectElement.options
1
  • 1
    Best answer for pure-javascript on modern browsers. +1
    – alihardan
    Mar 11, 2021 at 16:01
12

suppose the multiSelect is the Multiple-Select-Element, just use its selectedOptions Property:

//show all selected options in the console:

for ( var i = 0; i < multiSelect.selectedOptions.length; i++) {
  console.log( multiSelect.selectedOptions[i].value);
}
4
11

$('#select-meal-type :selected') will contain an array of all of the selected items.

$('#select-meal-type option:selected').each(function() {
    alert($(this).val());
});

0
10

Pretty much the same as already suggested but a bit different. About as much code as jQuery in Vanilla JS:

selected = Array.prototype.filter.apply(
  select.options, [
    function(o) {
      return o.selected;
    }
  ]
);

It seems to be faster than a loop in IE, FF and Safari. I find it interesting that it's slower in Chrome and Opera.

Another approach would be using selectors:

selected = Array.prototype.map.apply(
    select.querySelectorAll('option[selected="selected"]'),
    [function (o) { return o.value; }]
);
4
  • Isn't the functionality of the first one already in Javascript? Mar 7, 2016 at 16:28
  • 1
    Ok, got it. But the first one can be shorter. Just select.selectedOptions. Mar 7, 2016 at 16:34
  • 1
    That's a drawback of bare JS compared to using libraries. The selectedOptions property lacks in reliable browser support. Library like jQuery will hide that from you. A lot has changed since 2013 but a quick google shows that people still have issues with selectedOptions.
    – uKolka
    Mar 7, 2016 at 20:19
  • There's no need to use apply. Use call and you can avoid having to pass an array of arguments. Oct 4, 2022 at 17:50
8

Update October 2019

The following should work "stand-alone" on all modern browsers without any dependencies or transpilation.

<!-- display a pop-up with the selected values from the <select> element -->

<script>
 const showSelectedOptions = options => alert(
   [...options].filter(o => o.selected).map(o => o.value)
 )
</script>

<select multiple onchange="showSelectedOptions(this.options)">
  <option value='1'>one</option>
  <option value='2'>two</option>
  <option value='3'>three</option>
  <option value='4'>four</option>
</select>
7

If you need to respond to changes, you can try this:

document.getElementById('select-meal-type').addEventListener('change', function(e) {
    let values = [].slice.call(e.target.selectedOptions).map(a => a.value));
})

The [].slice.call(e.target.selectedOptions) is needed because e.target.selectedOptions returns a HTMLCollection, not an Array. That call converts it to Array so that we can then apply the map function, which extract the values.

1
  • 1
    Sadly this won't work everywhere, turns out IE11 does not have the field selectedOptions. The following does work however: Array.prototype.slice.call(field.querySelectorAll(':checked')) Jul 17, 2017 at 9:53
7

Check this:

HTML:

<select id="test" multiple>
<option value="red" selected>Red</option>
<option value="rock" selected>Rock</option>
<option value="sun">Sun</option>
</select>

Javascript one line code

Array.from(document.getElementById("test").options).filter(option => option.selected).map(option => option.value);
0
4

if you want as you expressed with breaks after each value;

$('#select-meal-type').change(function(){
    var meals = $(this).val();
    var selectedmeals = meals.join(", "); // there is a break after comma

    alert (selectedmeals); // just for testing what will be printed
})
4

Try this:

$('#select-meal-type').change(function(){
    var arr = $(this).val()
});

Demo

$('#select-meal-type').change(function(){
  var arr = $(this).val();
  console.log(arr)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="select-meal-type" multiple="multiple">
  <option value="1">Breakfast</option>
  <option value="2">Lunch</option>
  <option value="3">Dinner</option>
  <option value="4">Snacks</option>
  <option value="5">Dessert</option>
</select>

fiddle

0
4

Here is an ES6 implementation:

value = Array(...el.options).reduce((acc, option) => {
  if (option.selected === true) {
    acc.push(option.value);
  }
  return acc;
}, []);
1
  • This works great. It's interesting to note that because element.options is a live collection, it cannot be reduced. It must first be converted to an Array as seen in the above answer.
    – Brandon
    Jun 15, 2017 at 18:57
4

Building on Rick Viscomi's answer, try using the HTML Select Element's selectedOptions property:

let txtSelectedValuesObj = document.getElementById('txtSelectedValues');
[...txtSelectedValuesObj.selectedOptions].map(option => option.value);

In detail,

  • selectedOptions returns a list of selected items.
  • Specifically, it returns a read-only HTMLCollection containing HTMLOptionElements.
  • ... is spread syntax. It expands the HTMLCollection's elements.
  • [...] creates a mutable Array object from these elements, giving you an array of HTMLOptionElements.
  • map() replaces each HTMLObjectElement in the array (here called option) with its value (option.value).

Dense, but it seems to work.

Watch out, selectedOptions isn't supported by IE!

4

Something like the following would be my choice:

let selectElement = document.getElementById('categorySelect');
let selectedOptions = selectElement.selectedOptions || [].filter.call(selectedElement.options, option => option.selected);
let selectedValues = [].map.call(selectedOptions, option => option.value);

It's short, it's fast on modern browsers, and we don't care whether it's fast or not on 1% market share browsers.

Note, selectedOptions has wonky behavior on some browsers from around 5 years ago, so a user agent sniff isn't totally out of line here.

3

You can get as an array the values from the <select> at the submit of the form as this example :

const form = document.getElementById('form-upload');

form.addEventListener('change', (e) => {
    const formData = new FormData(form);
    const selectValue = formData.getAll('pets');
    console.log(selectValue);
})
<form id="form-upload">
  <select name="pets" multiple id="pet-select">
      <option value="">--Please choose an option--</option>
      <option value="dog">Dog</option>
      <option value="cat">Cat</option>
      <option value="hamster">Hamster</option>
      <option value="parrot">Parrot</option>
      <option value="spider">Spider</option>
      <option value="goldfish">Goldfish</option>
  </select>
</form>

1
  • FormData is a Web APIs facility, btw. It didn't first occur to me :)
    – Skj
    Sep 30, 2022 at 17:33
2

You Can try this script

     <!DOCTYPE html>
    <html>
    <script>
    function getMultipleSelectedValue()
    {
      var x=document.getElementById("alpha");
      for (var i = 0; i < x.options.length; i++) {
         if(x.options[i].selected ==true){
              alert(x.options[i].value);
          }
      }
    }
    </script>
    </head>
    <body>
    <select multiple="multiple" id="alpha">
      <option value="a">A</option>
      <option value="b">B</option>
      <option value="c">C</option>
      <option value="d">D</option>
    </select>
    <input type="button" value="Submit" onclick="getMultipleSelectedValue()"/>
    </body>
    </html>
2

You can use [].reduce for a more compact implementation of RobG's approach:

var getSelectedValues =  function(selectElement) {
  return [].reduce.call(selectElement.options, function(result, option) {
    if (option.selected) result.push(option.value);
    return result;
  }, []);
};
1
  • Array.prototype.filter would be a better option [].filter.call(ele.options, e => e.selected)
    – megawac
    Sep 6, 2016 at 18:36
2

My template helper looks like this:

 'submit #update': function(event) {
    event.preventDefault();
    var obj_opts = event.target.tags.selectedOptions; //returns HTMLCollection
    var array_opts = Object.values(obj_opts);  //convert to array
    var stray = array_opts.map((o)=> o.text ); //to filter your bits: text, value or selected
    //do stuff
}
0
1

Same as the earlier answer but using underscore.js.

function getSelectValues(select) {
    return _.map(_.filter(select.options, function(opt) { 
        return opt.selected; }), function(opt) { 
            return opt.value || opt.text; });
}
1

Works everywhere without jquery:

var getSelectValues = function (select) {
    var ret = [];

    // fast but not universally supported
    if (select.selectedOptions != undefined) {
        for (var i=0; i < select.selectedOptions.length; i++) {
            ret.push(select.selectedOptions[i].value);
        }

    // compatible, but can be painfully slow
    } else {
        for (var i=0; i < select.options.length; i++) {
            if (select.options[i].selected) {
                ret.push(select.options[i].value);
            }
        }
    }
    return ret;
};
1
  • selectedOptiongs is not supported in IE Nov 22, 2019 at 18:25
1

Here ya go.

const arr = Array.from(el.features.selectedOptions) //get array from selectedOptions property
const list = [] 
arr.forEach(item => list.push(item.value)) //push each item to empty array
console.log(list)
0
$('#application_student_groups option:selected').toArray().map(item => item.value)
2
  • 3
    Thanks for the answer. It would be great, if you could add a bit of explanation, how this is working and why you think, this is the best solution. Thanks! Jan 17, 2021 at 7:09
  • 1) $('#application_student_groups option:selected') return collection of selected object 2) .toArray() return the selected objects in array 3) and in map I return the option value (or you can return text) from the array we cannot judge a solution a best until we get a solution in the way we work. this is best solution for me as it works the way I work. hope you understand
    – Sahil Azim
    Jan 18, 2021 at 8:26
0

You can create your own function like this and use it everywhere

Pure JS

/**
* Get values from multiple select input field
* @param {string} selectId - the HTML select id of the select field
**/
function getMultiSelectValues(selectId) {
 // get the options of select field which will be HTMLCollection
 // remember HtmlCollection and not an array. You can always enhance the code by
 // verifying if the provided select is valid or not
  var options = document.getElementById(selectId).options; 
    var values = [];
    
   // since options are HtmlCollection, we convert it into array to use map function on it
    Array.from(options).map(function(option) {
        option.selected ? values.push(option.value) : null
    })

    return values;
}

you can get the same result using jQuery in a single line

$('#select_field_id').val()

and this will return the array of values of well.

Not the answer you're looking for? Browse other questions tagged or ask your own question.