Reputation: 776
I have a valuesArray
and a transcribedPoems
arrays. If a key is present in both of them, I want to add an option
to my select
element in both the Transcribed
and the All
subgroups. If not, then I want the option to be available only in the All
subrgoup. This is my code:
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);
The above code doesn't append anything to optGroupTranscribed
though. I noticed that if I take the optGroupAll.appendChild(option);
out from the condition, then I do have the transcribed poems in the transcribed
subgroup (and not in the All
one). I want the transcribed poems to also be in the All
subgroup though. What am I missing?
What I get:
<select>
<optgroup label="Transcribed">
<option value="2">another one</option>
</optgroup>
<optgroup label="All">
<option value="1">a manuscript</option>
</optgroup>
</select>
Expected result:
<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>
Upvotes: 2
Views: 1139
Reputation: 22274
do that this way...
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>
Upvotes: 1
Reputation: 350212
In one iteration of the forEach
loop, you only create one option
element, and so you cannot expect to have two as a result.
The second call to appendChild
actually moves the option
there, taking it out of the first option group.
You can call option.cloneNode(true)
to get around this.
Upvotes: 3
Reputation: 822
There's an interesting subtlety here. When you use createElement
, it creates an instance of HTMLElement (for the subclass option
). When you appendChild
that element to another element, it is placed in that element's DOM tree.
If you go to place that same element in another element's DOM tree, it would make it so that the overall tree (the one that would contain both optGroupTranscribed
and optGroupAll
) NOT a tree, since there would be one child option
shared by both elements.
Instead, you can call option.cloneNode()
to make a copy of the element. So, try changing it to:
optGroupTranscribed.appendChild(option.cloneNode());
Upvotes: 5