简体   繁体   中英

How do I use insertBefore on a nodeList thats length is changing?

I'm pretty new to js so forgive me if this is stupid, DOM work has been a pain for me.

When I run this, the if block executes fine. It adds a new node, making the length 2. However when I try to add another item, the else block returns this:

Uncaught NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.

which doesn't seem possible. What's the correct way to do this?

JS

'use strict';

let todoList = document.getElementById("todo-list");

let todoSubmit = () => {
    // User input
        let todoTextInput = document.getElementById("todo-form-text").value;
    // New item
        let todoItem = document.createElement("span");
        let todoItemInput = document.createElement("input");
        todoItemInput.setAttribute("type", "hidden");
        let todoText = document.createTextNode(todoTextInput);
        let todoLineBreak = document.createElement("br");
        todoItem.appendChild(todoItemInput);
        todoItem.appendChild(todoText);
        todoItem.appendChild(todoLineBreak);
    // Add to list
        if (todoList.childNodes.length === 1) {
            todoList.appendChild(todoItem);
        } else {
            todoItem.insertBefore(todoList.childNodes["1"], todoList);
        }
    return false;
}

Markup

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

    <form onsubmit="return todoSubmit()" id="todo-form">
        <input id="todo-form-text" type="text">
        <input id="todo-form-submit" type="submit">
    </form>

    <div id="todo-list">
    </div>

    <script src="script.js"></script>
</body>
</html>

Your insertBefore is in the wrong order

var insertedNode = parentNode.insertBefore(newNode, referenceNode);

https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore

JS

'use strict';

let todoList = document.getElementById("todo-list");

let todoSubmit = () => {
    // User input
        let todoTextInput = document.getElementById("todo-form-text").value;
    // New item
        let todoItem = document.createElement("span");
        let todoItemInput = document.createElement("input");
        todoItemInput.setAttribute("type", "hidden");
        let todoText = document.createTextNode(todoTextInput);
        let todoLineBreak = document.createElement("br");
        todoItem.appendChild(todoItemInput);
        todoItem.appendChild(todoText);
        todoItem.appendChild(todoLineBreak);
    // Add to list
        if (todoList.childNodes.length === 1) {
            todoList.appendChild(todoItem);
        } else {
            todoList.insertBefore(todoItem, todoList.childNodes[1]);
        }
    return false;
}

See https://jsfiddle.net/6j6a6eq8/1/

That can occur when you aren't using a front-end framework. A front-end like react.js and Angular.js watch the DOM for changes and update it. They kinda update the list of available DOM items. So when you add an item the browser isn't aware of the addition of the new node. That is why the browser is giving you the error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM