Suppression des options de la balise Select dans JavaScript Vanilla avec la boucle «for .. of»


10

Lorsque vous essayez de supprimer des options de la sélection, il en reste toujours une, pourquoi?

<select id="form-select">   
<option>111</option>
<option>222</option>
<option>333</option>
</select>

Ce JS ne fonctionne pas:

var t = document.querySelector('#form-select'); 
for(var i of t.options) {
      t.remove(i.index)
    }

Et cela ne fonctionne pas aussi:

for(var i of document.querySelector('#form-select').options) {
  i.remove()
}

Je sais qu'il existe d'autres solutions pour y parvenir, mais j'aimerais comprendre pourquoi cela ne fonctionne pas comme il le devrait

Réponses:


7

La .optionscollection est (malheureusement) en direct , donc itérer sur les éléments de la collection en direct un par un et .removechacun entraînera la conservation de chaque élément impair. (Par exemple, dès que vous supprimez le premier élément, le [0]e élément de la collection deviendra immédiatement le prochain élément de la collection - ce qui était auparavant [1]deviendra [0](puis une fois que vous accédez à l'index suivant à [1], le nouvel élément à la position 0 ne sera pas répété)

Utilisez document.querySelectorAllplutôt, qui retourne une collection qui est statique:

for (const option of document.querySelectorAll('#form-select > option')) {
  option.remove();
}
<select id="form-select">
  <option>111</option>
  <option>222</option>
  <option>333</option>
</select>

Vous pouvez également vous propager dans un tableau (statique) avant de supprimer des éléments ::

for (const option of [...document.querySelector('#form-select').options]) {
  option.remove();
}
<select id="form-select">
  <option>111</option>
  <option>222</option>
  <option>333</option>
</select>

Une autre option qui se produit parce que la collection est en direct (mais ne devrait probablement pas être utilisée, car elle n'est pas intuitive):

const { options } = document.querySelector('#form-select');
while (options.length) {
  options[0].remove();
}
<select id="form-select">
  <option>111</option>
  <option>222</option>
  <option>333</option>
</select>


3

Vous supprimez des éléments d'un tableau lorsque vous parcourez le tableau. Vous avez donc:

["one","two","three"]

puis vous supprimez l'élément à l'index 0, qui est "un", vous laissant avec:

["two","three"]

Ensuite, vous supprimez l'élément à l'index 1, qui est "trois", vous laissant avec:

["two"]

il n'y a pas d'élément à l'index 2, donc la boucle s'arrête.

Parcourez le tableau en sens inverse à la place:

const t = document.querySelector("#form-select")

for (let i = t.options.length-1; i >= 0; i--) {
  t.removeChild(t.options[i])
}
<select id="form-select">
  <option>111</option>
  <option>222</option>
  <option>333</option>
</select>


Ce .optionsn'est pas un tableau, qui est la source du problème - c'est plutôt un HTMLCollection, qui est en direct. S'il s'agissait d'un tableau, il serait statique et il n'y aurait aucun problème.
CertainPerformance

1
@CertainPerformance la suppression d' éléments d'un tableau que vous itérer à travers elle fait la cause du problème que je l' ai illustré.
symlink

1
@CertainPerformance Un HTMLOptionsCollectionobjet agit dans ce contexte comme un tableau.
symlink

2

Je vois que votre objectif principal est de comprendre le processus qui fait que cela se produit, donc cela devrait illustrer le problème pour vous:

var arr = ["one", "two", "three", "four", "five", "six"];

for(var i = 0; i < arr.length; i++){
	console.log("i is " + i + ", so we are removing \"" + arr[i] + "\" from " + JSON.stringify(arr) + ".");
	arr.splice(i, 1);
	console.log("After that removal, the array is " + JSON.stringify(arr) + ". We'll now iterate i to " + (i + 1) + " and continue the loop.");
}
console.log("i is too high to grab a value from the array, so we're finished. We're left with " + JSON.stringify(arr) + ".");

Cette boucle passe par exactement le même type de processus que votre boucle "for .. of" passe pour vous laisser des extras dans le résultat final. Le problème est qu'il détruit ses propres indices en itérant à travers eux, changeant ainsi la valeur à laquelle il ifait vraiment référence. Lorsque je suis confronté à ce problème, j'aime parcourir le tableau en arrière, donc je ne suis pas affecté par ma propre destruction, comme ceci:

var arr = ["one", "two", "three", "four", "five", "six"];

for(var i = arr.length - 1; i >= 0; i--){
	console.log("i is " + i + ", so we are removing \"" + arr[i] + "\" from " + JSON.stringify(arr) + ".");
	arr.splice(i, 1);
	console.log("After that removal, the array is " + JSON.stringify(arr) + ". We'll now iterate i to " + (i - 1) + " and continue the loop.");
}
console.log("i is too low to grab a value from the array, so we're finished. We're left with " + JSON.stringify(arr) + ".");

J'espère que cela vous aidera à bien comprendre ce qui se passe ici. Si vous avez des questions, n'hésitez pas à me laisser un commentaire.


0

Vous parcourez le même tableau où l'index change une fois que vous avez supprimé l'élément du tableau. Voici l'exemple où vous pouvez parcourir les options sans index et le supprimer du tableau.

var selectOptions = document.querySelectorAll('#remove-option>option');
selectOptions.forEach(function(selectOption) {
  selectOption.remove();
  selectOption = null;
});

Voici le violon

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.