Search code examples
javascriptuser-interfacedombootstrap-5web-frontend

Dynamically remove node from parent node


working on an application that requires adding and removal of items as need. The UI is displayed in the image below:

enter image description here

Work flow: On click of the add icon a new column is added which allows for assignment and on click of the delete icon marked "x", a column is removed from the list. All these functionalities work. i.e. columns are added and removed.

issue:

When a column is added by clicking the add button, an error is thrown in the console when an attempt is made to remove that column. so lets say, by default there was two columns initially, then a third column was added by clicking the add button, hen an attempt is made to remove that third column the error is thrown.

Error:

Logic.js:238 Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node. at HTMLElement.

codes:



 /**
         * helper function to retrieve DOM elements
         * @param {any} elem
         * @returns
         */
        const getElements = (elem) => {
            const deleteBtns = Array.from(elem.getElementsByClassName("delete-btn"));
            const permissions = elem.getElementsByClassName("permissions-row") || elem

            const elements = {
                row: permissions,
                button: deleteBtns
            }
            return elements;
        }

   /*** Creates new permissions for the permission edit modal ****/
        const addColumns = (elem) => {
            elem.querySelector(".add-permission").addEventListener("click", () => {
                const permsRow = getElements(elem).row
                const col = elem.querySelector(".col-6").cloneNode(true)
                console.log(permsRow[0])
                permsRow[0].appendChild(col);
                
                deleteColumns(permsRow[0])
            } )
            
        }

 /**
         *  Deletes permissions from the permissions edit modal
         */
        const deleteColumns = (elem) => {
            const deleteBtns = getElements(elem).button;
            const permissions = getElements(elem).row;
            
            deleteBtns.forEach(btn => {
                btn.addEventListener("click", (event) => {
                    updatePermissions(elem);
                    const currentPermission = event.target.parentNode.parentNode
                    Swal.fire({
                        icon: 'question',
                        title: 'Delete',
                        text: 'Do you want to delete this permission?!',
                    })
                    console.log(permissions);
                    if (deleteBtns.length === 1) return;
                    if (permissions.length === 0) {
                        console.log(deleteBtns.length)
                        elem.removeChild(currentPermission)
                    } else {
                        permissions[0].removeChild(currentPermission);
                    }
                   


                   
                })
            })

        }


Any insights as to why I am getting the above error in the console would be highly appreciated.

Thanks

Tried parsing the cloned node. used helper function. But not working


Solution

  • The event.target node may not always be the same (i.e. <button><span>x</span></button> could be the button or the span). Instead of always moving up a finite two levels with event.target.parentNode.parentNode try going up to the intended node with event.target.closest('.col-6') this will find the first ancestor that matches the selector.

    https://developer.mozilla.org/en-US/docs/Web/API/Element/closest