nick_rinaldi
nick_rinaldi

Reputation: 707

Why does HTML button generate 'ul' node only once when clicked multiple times?

Let me clarify, my below code is doing what I want.

I'm working on a simple todo app. Right now, everytime the button is clicked on the page, it runs the createListElem() function. The first line of code inside this function appends our ul element to the body. However, it doesn't repeatedly add new ul elements when the button is clicked. It only adds li elements to that ul element.

Let me again clarify, that is fine and is what I want it to do.

Everytime we hit that button, we run the function. So in theory, everytime we hit that button, a new ul_node is appended to the body? Or is it because I intialized the variable holding the ul_node outside the function, it doesn't append a new ul_node?

Basically my question is: Why when we click that button, the function appends one ul element to the page, rather than a ul element every button click?

Hope I'm clear! My code is below


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./style.css">

    <title>Nick's Todo List</title>
</head>

<body>
    <h1 class="main-header">Nick's Todo List</h1>
    <div class="input-container">
        <input id="input-box" type="text" value="bro bro">
        <input onclick="createListElem()" id="add-btn" type="button">
        <select name="task-completion" id="task-completion">
            <option value="All">All</option>
            <option value="Completed">Completed</option>
            <option value="Uncompleted">Uncompleted</option>
        </select>
    </div>
    <script src="./app.js"></script>
</body>

</html>

JavaScript

const ul_node = document.createElement("ul");

function createListElem() {

    document.body.appendChild(ul_node);

    const box_value = document.getElementById('input-box').value;

    const task = document.createTextNode(box_value);

    const li_node = document.createElement('li');

    li_node.appendChild(task)

    ul_node.appendChild(li_node)

}

Upvotes: 0

Views: 99

Answers (2)

Scott Marcus
Scott Marcus

Reputation: 65835

Everytime we hit that button, we run the function. So in theory, everytime we hit that button, a new ul_node is appended to the body? Or is it because I intialized the variable holding the ul_node outside the function, it doesn't append a new ul_node?

Yes, that's correct. The code to create the ul element exists outside of your function and is executed only once. It's the code within your callback function that runs every time you click the button. Now, the first time you click the button the new ul is appended to the body, but from there on, when you ask for the ul to be appended to the body, you are asking for the one that already exists to be appended and when that happens, append just moves the element from where it is to where you told it to go. Since where it is and where you are telling it to go are the same location, no new ul seems to appear.

If you want to create a new ul to add below the existing one each time, you'll need to move the createElement line into the function.

Upvotes: 2

Jaromanda X
Jaromanda X

Reputation: 1

When you use parentElement.appendChild(element) the existing element is moved from its current location to the new location

The first time, this results in the element being added to the DOM

Second and subsequent calls simply moves the element from its current location in the DOM to the new location - in this case back to where it was, since it already is the last child of document.body


The only time this code could be a problem is if other elements are appended after this UL ... in that case, calling createListElem would move the UL element after those elements

One way to avoid this is to check if ul is already in the DOM - i.e. it has a .parentElement (or .parentNode) and only append it if it does not

const ul_node = document.createElement("ul");
function createListElem() {
    if (!ul_node.parentElement) {
        document.body.appendChild(ul_node);
    }
    // ... etc
}

Upvotes: 2

Related Questions