0

to keep this short and simple, I have a select menu where I am constantly appending and removing elements to a select dropdown. I looked at How do I clear all options in a dropdown box? and Remove values from select list based on condition but had no luck. I am trying to do something like this.

var select = document.getElementById('model-menu');

Now if I do...

select.options //returns an array [with a length of 24]

enter image description here

for (var i = 1; i <= select.options.length; i++) { 
    select.remove(i) 
}

The problem now is that... it only removed half.

select.length //12

enter image description here

It's really wierd. This is where it gets even wierder. If I do...

for (var i = 0; i < select.options.length; i++) {
    console.log(i) //24 23 22 21....
}

IT STOPS AT 12.

I am not looking for an exact solution to this problem, but this is some absolute nonsense that I have been dealing with for the past few hours and If someone can direct me to where this issue MIGHT be happening it will save me a lot of stress :)

Community
  • 1
  • 1
dsomel21
  • 576
  • 2
  • 8
  • 27
  • 2
    You are removing from collection that you iterate over, that is your problem ;). – xszaboj Jan 31 '17 at 16:54
  • If you want just remove them all. Have a look on this question: [How do I empty an array in JavaScript?](http://stackoverflow.com/questions/1232040/how-do-i-empty-an-array-in-javascript) – xszaboj Jan 31 '17 at 16:57
  • 2
    Possible duplicate of [How do I empty an array in JavaScript?](http://stackoverflow.com/questions/1232040/how-do-i-empty-an-array-in-javascript) – xszaboj Jan 31 '17 at 16:58
  • @xszaboj believe me I tried setting it to an empty array, it didn't work. It might be because select is static... Not dynamic. I am going to read up on Nodelists right now – dsomel21 Jan 31 '17 at 17:16
  • Have you tried `$(select.options).clear()` ?... instead of iterating one by one? – David Espino Jan 31 '17 at 17:30
  • So, have you tried all of the answers in your first link? Because there are many more options than using the for loop (and the comments on the accepted answer indicate it is incorrect). – Heretic Monkey Jan 31 '17 at 17:30

1 Answers1

2

You can try this way:

function clearItems() {
  var select = document.getElementById("select1");
  for(i = select.options.length - 1 ; i >= 0 ; i--){
      select.remove(i);
  } 
}
<select id="select1">
  <option value="Item A">Item A</option>
  <option value="Item B">Item B</option>
  <option value="Item C">Item C</option>
  <option value="Item D">Item D</option>
</select>

<input type="button" value="Clear Items" onclick="clearItems()" />

And this is why you code not works properly:

see what happens when you loop from beginning to N as:

for (var i = 0; i < select.options.length; i++) { 
  select.remove(i);
}

//initial length = 4 (0:A, 1:B, 2:C, 3:D)
//i=0  =>  remove(0)  =>  Item A will be removed
//now we have: 0:B, 1:C, 2:D  ,  length=3
//i=1  =>  remove(1)  =>  this will remove Item C (instead of Item B)
//now we have: 0:B, 1:D  ,  length=2  
//... so it will skip one item at each iteration!
//i=2  =>  (length=2) exit loop!
//... as length is decreasing at each loop 
//... and the loop stop condition will be evaluated at each iteration,
//... so we will stop at half of the loop!

//to solve this issue, we could also use this way:

var n1 = select.options.length; // cache the original length

for(i = 0 ; i < n1; i++){
  select.remove(0);
}     
S.Serpooshan
  • 7,608
  • 4
  • 33
  • 61
  • Yes! I came here to answer my own question but you did it for me Someone over in the Reactiflux community explained that this was a NodeList concern, and if I was iterating it the way I was, I would be going out of bounds. – dsomel21 Jan 31 '17 at 18:04