36

From what I understand a option elements that popuate select elements in HTML are an array.
So basically what i want to do is return an array string that is separated by commas.

Tried to do selecbox.options.join(',');, but got an error that its not supported; anyone have an idea why?

1
  • 2
    You want to return an array of elements converted to a string, separated by comma -- this makes no sense. It'll basically be [object HTMLOptionElement], [object HTMLOptionElement] do you mean you want the values of each option separated by comma, or convert an array-like object to a simple array? Commented May 26, 2011 at 12:15

8 Answers 8

37

It is not an array. It is an HTMLCollection. It is "array-like"

In 2022, a week before EOL of Internet Explorer 11, the simplest vanilla JavaScript solution is using spread and Array map

UPDATE: Array.from is actually preferable to the spread since it is more obvious what is going on

const opts = document.querySelectorAll("select option"); 
// we can use forEach on the resulting HTMLCollection 
// but map needs to be spread to array
const vals = Array.from(opts) // or [...opts]
  .map(el => el.value); 
console.log(vals);
<select>
<option value="Please select">Text 0</option>
<option value="one">Text 1</option>
<option value="two">Text 2</option>
<option value="three">Text 3</option>
</select><br/> 
The above select has the following option values:<br/>
<span id="result"></span>


Older answer that is compatible with IE11

from http://api.jquery.com/jQuery.each/ which CAN iterate over either:

Iterate over both objects and arrays. Arrays and array-like objects with a length property (such as a function's arguments object) are iterated by numeric index, from 0 to length-1. Other objects are iterated via their named properties.

Each HTML Option element has a value and a text and some more attributes.

A simple for loop can be used

vals = []
var sel = document.querySelector("select");
for (var i=0, n=sel.options.length;i<n;i++) { // looping over the options
  if (sel.options[i].value) vals.push(sel.options[i].value);
}

the Array.apply posted by typeracer will return an array of HTMLOptionElements which still needs to be looped over or mapped to get at the values and texts

Here are a few versions that will return the same.

This fiddle will run in IE11 too

var vals, sel = document.querySelector("select"), show=function(vals) {$("#result").append("[" + vals.join("][") + "]<hr/>");}
var supportsES6 = function() {try{new Function("(a = 0) => a");return true;}catch (err) {return false;  }}();


// jQuery mapping jQuery objects - note the "this" and the .get()
vals = $('select > option').map(function() {return this.value;}).get();
show(vals);

// plain JS using loop over select options
vals = [];
for (var i = 0, n = sel.options.length; i < n; i++) { // looping over the options
  if (sel.options[i].value) vals.push(sel.options[i].value); // a bit of testing never hurts
}
show(vals);

// Plain JS using map of HTMLOptionElements - note the el
vals = Array.apply(null, sel.options).map(function(el) { return el.value; });
show(vals);

// ES6 JS using spread and map of HTMLOptionElements - note the fat arrow and el
if (supportsES6) 
  document.write(`<script>

  vals = [...sel.options].map(el => el.value);

show(vals);
<\/script>`
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<select>
<option value="Please select">Text 0</option>
<option value="one">Text 1</option>
<option value="two">Text 2</option>
<option value="three">Text 3</option>
</select><br/> 
The above select has the following option values:<br/>
<span id="result"></span>

Sign up to request clarification or add additional context in comments.

4 Comments

as far as i know it is an options array ( otherwise how come we can access items by index? like selectbox.options[1] ?) what i need it to take all values ( not just selected values ), connect them with commas and return the result.
"The options property is an array of all the options in a particular Select object. There is one element (numbered in ascending order from zero) for each <OPTION> tag."
ok, so from your edit i understand the selecbox.options is actually an object array, and not an regular array. is that right ?
A shorter version of the apply variant is Array.apply(null, sel.options).map(el => el.value) by using array functions and the shorter return
30

The most concise solution is this:

Array.apply(null, selectbox.options)

Array.apply calls the Array constructor with the first argument as the context (i.e. this) and the second argument which is any array-like object (MDN reference).

We pass null for the first argument because we're not trying to call a method on a specific object, but rather a global constructor.

So in general,

Array.apply(null, A)

Will create a proper array containing the elements of any "array-like" object A.

3 Comments

MDN currently isn't very helpful with browser compatibility, but with some quick testing on Chrome, FF, and IE, it seems Modern Browser Friendly (c) 2016. Very nice answer.
And to get the text of those options only: Array.apply(null, selextbox.options).map(function(el){return el.text;});
NOTE: Array.apply(null, document.querySelector("select").options) will still produce [object HTMLOptionElement],[object HTMLOptionElement],[object HTMLOptionElement],[object HTMLOptionElement] - so additional mapping or looping is needed to get values and texts
7

To get all the values into an array:

var options = document.getElementById('selectId').options;
var values = [];
var i = 0, len = options.length;

while (i < len)
{
  values.push(options[i++].value);
}
alert(values.join(', '));

Fiddle: http://jsfiddle.net/garreh/64pyb/1/


wow a long way to do something short

Well you can use a for loop, not much shorter but more ugly;

for (var options = document.getElementById('selectId').options,
          values, i = 0, len = options.length; i < len;i++)
  values.push(options[i].value);

alert(values.join(', '));

Then again it's a shame you're not using a library like jQuery. You could do:

$('select > option').map(function() { return this.value; }).get();

Comments

7

The spread operator makes it really easy ([ ...ElementList ]).

So for your case you can do the following:
arr = document.getElementById('store-locator-region')

Then convert the html select element to an object array using the spread operator:
newArr = [...arr]

And then iterate over your object array to get your final array:
countryList = newArr.map(a => a.value) (97) ["XE", "AL", "DZ", "AD", "AR", "AM", etc..]

1 Comment

deserves more fame!
5

selecbox.options is a collection (nodeList). You can iterate over its elements like you do with an array and push the members of the collection to a real array.

For the record: in all browsers but IE<9 you can use [].slice.call(selecbox.options);1 to quickly convert a collection to an array.

So a crossbrowser way to convert a nodeList collection to array would be:

function coll2array(coll){
    var ret = [];
    try {
       ret = [].slice.call(coll)
    }
    catch(e) {
        for (var i =0;i<coll.length;i++){
            ret.push(coll[i]);
        }
    }
    return ret;
}

[edit] Nowadays (ES2015 and up) we can use Array.from(options) or [...options].

1 or Array.prototype.slice.call([some collection])

2 Comments

thx for the info, but as best practice i prefer a CrossBrowser solution.
Also you still need to process this new array of HTMLOptionElement object
2

select.options is not an array, it is a NodeList which shares some of the features of an array and so can be described as array like. a NodeList doesn't have the methods that an Array has, but you can call or apply those methods to it. In your case you can call the join method like this:

var opts = yourSelect.options;
var str = Array.prototype.join.call( opts, ',' );

Alternatively you could convert the NodeList into a true Array with a similar technique

// slice returns a new array, which is what we want
var optsArray = Array.prototype.slice.call( opts );

2 Comments

However that returns [object HTMLOptionElement],[object HTMLOptionElement],[object HTMLOptionElement],[object HTMLOptionElement]
@mplungjan - true, [object HTMLOptionElement] is the result of a call to Option.toString(). So using this answer as a solution is pretty useless. My answer does explain the Why? part of the OP's question tho
1

You can join an array of strings, but an option is not a string, it's an object with all kinds of properties like value and text. Which should it use to join?

You just have to write a loop to append all values you want.

Or use a library and use some each() function to loop through the options.

2 Comments

use a library ? for this function ? add 65k to my project for a simple thing ? thats a bad advice.
I meant only when you're already using a library. I just wanted to make the options clear.
1

I wonder why no one suggested this:

$(selecbox).find("option").map((index, option) => {
  // do stuff
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.