<div class="container">
<select class="btn" name="item">
<option>Alpha</option>
<option>Beta</option>
<option>Gamma</option>
<option>Theta</option>
</select>
<input type="text" class="desc" name="desc">
</div>
In this example, element selected by default in the "select" dropdown is "Alpha". I want to clone the complete node with values. If i select a different value in the dropdown and enter some text in the input box, and then clone the node, only the text box value is cloned. The value of "select" dropdown in the new object remains the default (Alpha).
Why is the behavior of cloning different for "select" vs "input"?
var parent = document.querySelector(".container");
var button = parent.querySelector(".btn");
var textbox = parent.querySelector(".desc");
> textbox.value
< "some random text"
> button.value
< "Gamma"
var cloned = parent.cloneNode(true);
var childButton = cloned.querySelector(".btn");
var childTextbox = cloned.querySelector(".desc");
> childTextbox.value
< "some random text"
> childButton.value
< "Alpha"
When you change a selection, the state of the selection is stored in browser and the cloned node will never include the state of object/ element which is changed and/or stored by browser.
But for input
, it is stored as a value of the attribute value
and get cloned.
To clone a node with selected value,
You should detect the change event and add a selected
attribute to it.
That is, add an event listener for select
for change
event.
Then in the callback function, set the attribute selected
to that object by using
selectElement.options[selectElement.selectedIndex].setAttribute("selected","");
Run the snippet below.
Select any value from the list and type something in the text box and click clone button.
var parent = document.querySelector(".container");
var button = parent.querySelector(".btn");
var textbox = parent.querySelector(".desc");
console.log(button.value);
console.log(textbox.value);
function update(val){
val.options[val.selectedIndex].setAttribute("selected","");
}
function clone(){
var cloned = parent.cloneNode(true);
document.querySelector(".container-2").appendChild(cloned);
var childButton = cloned.querySelector(".btn");
var childTextbox = cloned.querySelector(".desc");
console.log(button.value);
console.log(textbox.value);
}
<div class="container">
<select class="btn" name="item" onchange="update(this);">
<option>Alpha</option>
<option>Beta</option>
<option>Gamma</option>
<option>Theta</option>
</select>
<input type="text" class="desc" name="desc">
</div>
<button onclick="clone();">Clone</button>
<div class="container-2"></div>
I use the getElementsByClass() method to get the interesting elements.Then via for loop I add an onchange event to clone the container.Note the at the end of the function i assign the value pf the parent select element to the cloned select elm.
var parent = document.getElementsByClassName("container");
var button = document.getElementsByClassName("btn");
for(var i=0;i<button.length;i++){
button[i].onchange=function(){
var cloned = parent[0].cloneNode(true);
console.log(cloned);
document.body.appendChild(cloned);
cloned.childNodes[1].value=this.value;
};
}
<div class="container">
<select class="btn" name="item">
<option>Alpha</option>
<option>Beta</option>
<option>Gamma</option>
<option>Theta</option>
</select>
<input type="text" class="desc" name="desc">
</div>
Cloning a <select>
does not copy the value=
property on <option>
s.
This happens because changing the attribute changes the state of the form control, but does not change the value of the HTML selected attribute of the element.
You can read more about it in W3 specs.
In your example, if you check the value of the parent
node you will see that only that element will have the correct selected value and none of its clones.