I have a requirement where I have to pickup the last .div
within a container and apply some business logic to it. The selection of the last .div
has to be dynamic because the user has the option to add/remove .div
elements.
Initially I tried with querySelectorAll
but it did not seem to work. So I decided to change it to getElementsByClassName
and surprisingly it worked with the same logic. Can somebody please help me with the reason for why the remove_div
doesn't work while the second one (remove_div_2
) does?
Note: I am not looking for a fix/solution to the issue because I have already proceeded with the second option. I just want to know the reason why the option with querySelectorAll
doesn't work.
Below is my code:
HTML:
<div id='container'>
<div id='div1' class='div'>This is Div 1</div>
<div id='div2' class='div'>This is Div 2</div>
<div id='div3' class='div'>This is Div 3</div>
</div>
<button type='button' id='append_div'>Append Div</button>
<button type='button' id='remove_div'>Remove Div</button>
<button type='button' id='remove_div_2'>Remove Div 2</button>
JavaScript:
window.onload = function () {
var elementToStyle = document.querySelectorAll("#container .div");
elementToStyle[elementToStyle.length - 1].classList.add('red');
document.getElementById('append_div').onclick = function () {
var divToInsert = document.createElement('div');
divToInsert.id = 'new_div';
divToInsert.className = 'div';
divToInsert.innerHTML = 'This is an appended div';
document.getElementById('container').appendChild(divToInsert);
var elToStyle = document.querySelectorAll("#container .div");
for (i = 0; i < elToStyle.length; i++)
elToStyle[i].classList.remove('red');
elToStyle[elToStyle.length - 1].classList.add('red');
};
document.getElementById('remove_div').onclick = function () {
var elToStyle = document.querySelectorAll("#container .div");
document.getElementById('container').removeChild(elToStyle[elToStyle.length - 1]);
elToStyle[elToStyle.length - 1].classList.add('red');
};
document.getElementById('remove_div_2').onclick = function () {
var elToStyle = document.getElementsByClassName('div');
document.getElementById('container').removeChild(elToStyle[elToStyle.length - 1]);
elToStyle[elToStyle.length - 1].classList.add('red');
};
}
If you want to reference the last division element just do the following...
..and then apply your
querySelector
.The reason is because
querySelectorAll
method returns a static list. Any changes made to the document after thequerySelectorAll
is used (likeremoveChild
in this case) will not be reflected in the list of nodes returned. HenceelToStyle[elToStyle.length - 1]
would still point to the node that was removed.Whereas,
getElementsByClassName
on the other hand returns a live list of nodes. This implies thatelToStyle[elToStyle.length - 1]
would always point to the last.div
irrespective of any changes were done to the document after the node list was prepared or not.Below is the extract from the official documentation available here
Note: You can see this by doing a
console.log(elToStyle);
both before and after theremoveChild
.