Why does my button need to be clicked twice for the onclick event to trigger? There're some other thread on stackoverflow with the same problem, but in all the thread i found, the original poster puts the event handler inside the function. It's not like that with my code.
Html
<body>
<ul id="parentList">
<li>First child</li>
<li>Second child</li>
<li>Third child</li>
<li>Forth child</li>
<li>Fifth child</li>
</ul>
<button type="button" id="delete">Delete first child</button>
</body>
Script:
var parentList = document.getElementById("parentList");
document.getElementById("delete").onclick = function() {
parentList.removeChild(parentList.firstChild);
};
Demonstration: onclick-error
Why does my button need to be clicked twice for the onclick event to trigger? There're some other thread on stackoverflow with the same problem, but in all the thread i found, the original poster puts the event handler inside the function. It's not like that with my code.
Html
<body>
<ul id="parentList">
<li>First child</li>
<li>Second child</li>
<li>Third child</li>
<li>Forth child</li>
<li>Fifth child</li>
</ul>
<button type="button" id="delete">Delete first child</button>
</body>
Script:
var parentList = document.getElementById("parentList");
document.getElementById("delete").onclick = function() {
parentList.removeChild(parentList.firstChild);
};
Demonstration: onclick-error
Share Improve this question asked Apr 26, 2017 at 13:55 Nhu Thai Sanh NguyenNhu Thai Sanh Nguyen 1891 gold badge1 silver badge8 bronze badges 5- Did you try defining parentList in the function? – Felix Haeberle Commented Apr 26, 2017 at 14:00
- @FelixHäberle What do u mean?? It needs to be clicked twice, but the <li> child does get removed, so the browser must recognize parentList isn't it? – Nhu Thai Sanh Nguyen Commented Apr 26, 2017 at 14:02
- I think parentList is out of scope at the first click. Copy your first js line into the function. – Felix Haeberle Commented Apr 26, 2017 at 14:04
-
@FelixHäberle what do you mean that
parentList
is out of scope? – evolutionxbox Commented Apr 26, 2017 at 14:07 -
Why not use
firstElementChild
instead? That way you can be sure you're removing an element, not a text node. developer.mozilla/docs/Web/API/ParentNode/firstElementChild – evolutionxbox Commented Apr 26, 2017 at 14:08
4 Answers
Reset to default 7The first "element" within the parentList is whitespace. You can see this by console logging the element within the event listener.
You therefore need to only filter out the li
elements within the parent item.
document.getElementById("delete").onclick = function() {
var listItems = document.querySelectorAll("#parentList > li");
if (listItems.length > 0) {
listItems[0].remove();
}
};
https://jsfiddle/ofLvac32/13/
You could also use parentList.firstElementChild
instead of parentList.firstChild
, which filters out any invalid nodes (whitespace).
An example of this
var parentList = document.getElementById("parentList");
document.getElementById("delete").onclick = function() {
parentList.removeChild(parentList.firstElementChild);
};
https://jsfiddle/ofLvac32/37/
With elementChild
, you look for any child, including white spaces.
You could use parentList.firstElementChild
instead to get the first child element.
There is nothing wrong with your click handler on the button. The problem is with the way you are removing the first child. If you add this small change to your function:
var parentList = document.getElementById("parentList");
document.getElementById("delete").onclick = function() {
console.log(parentList.removeChild(parentList.firstChild));
};
You will notice that the first click logs out some empty spaces with a line break. This appears to be an empty text node. The second click removes the first <li>
and so on...
As you could see in following snippet, first child is string of new line and spaces:
function loaded(){
document.getElementById("parentList");
var firstChild = parentList.firstChild;
console.log("First child: \"" + firstChild.data + "\"");
}
<body onload="javascript:loaded()">
<ul id="parentList">
<li>First child</li>
<li>Second child</li>
<li>Third child</li>
<li>Forth child</li>
<li>Fifth child</li>
</ul>
</body>
You could use firstElementChild property to get only the first child Element, like:
var parentList = document.getElementById("parentList");
document.getElementById("delete").onclick = function() { parentList.removeChild(parentList.firstElementChild);
};
<ul id="parentList">
<li>First child</li>
<li>Second child</li>
<li>Third child</li>
<li>Forth child</li>
<li>Fifth child</li>
</ul>
<button type="button" id="delete">Delete first child</button>