Tengo una valuesArray de valores y una matriz de poemas transcribedPoems . Si hay una clave presente en ambos, quiero agregar una option a mi elemento de select en los subgrupos Transcribed y All . De lo contrario, quiero que la opción esté disponible solo en el subgrupo All . Este es mi código:
let valuesArray = [ ["1", "a manuscript"], ["2", "another one"] ] const transcribedPoems =['2'] let optGroupTranscribed = document.createElement("optgroup"); optGroupTranscribed.setAttribute("label", "Transcribed") let optGroupAll = document.createElement("optgroup"); optGroupAll.setAttribute("label", "All") let select = document.createElement("select"); valuesArray.forEach(function(element) { let option = document.createElement("option"); option.value = element[0]; option.text = element[1]; if (transcribedPoems.includes(element[0])) { optGroupTranscribed.appendChild(option); optGroupAll.appendChild(option); } else { optGroupAll.appendChild(option); } }); select.appendChild(optGroupTranscribed); select.appendChild(optGroupAll); document.getElementById("manifests").appendChild(select); Sin embargo, el código anterior no agrega nada a optGroupTranscribed . Noté que si tomo optGroupAll.appendChild(option); fuera de la condición, entonces tengo los poemas transcritos en el subgrupo transcribed (y no en el All ). Sin embargo, quiero que los poemas transcritos también estén en el subgrupo All . ¿Qué me estoy perdiendo?
Lo que consigo:
<select> <optgroup label="Transcribed"> <option value="2">another one</option> </optgroup> <optgroup label="All"> <option value="1">a manuscript</option> </optgroup> </select>Resultado Esperado:
<select> <optgroup label="Transcribed"> <option value="2">another one</option> </optgroup> <optgroup label="All"> <option value="1">a manuscript</option> <option value="2">another one</option> </optgroup> </select>En una iteración del bucle forEach , solo crea un elemento de option , por lo que no puede esperar tener dos como resultado.
La segunda llamada a appendChild en realidad mueve la option allí, sacándola del primer grupo de opciones.
Puede llamar a option.cloneNode(true) para evitar esto.
Aquí hay una sutileza interesante. Cuando usa createElement , crea una instancia de HTMLElement (para la option de subclase). Cuando appendChild ese elemento a otro elemento, se coloca en el árbol DOM de ese elemento.
Si va a colocar ese mismo elemento en el árbol DOM de otro elemento, el árbol general (el que contendría tanto optGroupTranscribed como optGroupAll ) NO sería un árbol, ya que habría una option secundaria compartida por ambos elementos.
En su lugar, puede llamar a option.cloneNode() para hacer una copia del elemento. Por lo tanto, intente cambiarlo a:
optGroupTranscribed.appendChild(option.cloneNode());hazlo de esta manera...
doc :
optionElement = new Option(text, value, defaultSelected, selected)
const newElm = (tag, props={}) => Object.assign(document.createElement(tag), props) , transcribedPoems = ['2'] , valuesArray = [ ['1', 'a manuscript'] , ['2', 'another one' ] ] , mySelect = document .querySelector('#manifests') .appendChild( newElm('select',{name:'select',id:'objectAssign'})) ; let optGroupTranscribed = mySelect.appendChild(newElm('optgroup',{label:'Transcribed'})) , optGroupAll = mySelect.appendChild(newElm('optgroup',{label:'All'})) , doSelect = true ; valuesArray.forEach(([val,lib]) => { if ( transcribedPoems.includes(val)) { optGroupTranscribed.appendChild( new Option(lib,val,doSelect,doSelect) ) doSelect = false } optGroupAll.appendChild( new Option(lib,val) ) }) <div id="manifests"></div>