skip to Main Content

The way I’m implementing is when i click the star-icon, it’ll turn solid and will be added to Favorites and it’ll be removed from Favorites when the star-icon is clicked again.

This is the error I get:
Failed to execute ‘removeChild’ on ‘Node’: The node to be removed is not a child of this node. at remove From Favorites.

document.addEventListener("DOMContentLoaded", function() {
    const openStudyResource = document.getElementById("openStudyResource")
    const favorites = document.getElementById("favorites")
    const studyResourceContainer = document.getElementById("studyResourceContainer")
    const jsonBoxes = document.getElementById("resources")

    const selectedResource = new Set();

    openStudyResource.addEventListener("click", function(){
        studyResourceContainer.style.left = "60px";
    })

    function addToFavorites(resource){
        const clone = resource.cloneNode(true);
        favorites.appendChild(clone);
    }
    
    function removeFromFavorites(resource){
        favorites.removeChild(resource);
    }

    function toggleFavorites(starIcon, resource){
        console.log(favorites)
        const isFav = starIcon.dataset.favorites === "true";

        if(isFav){
            starIcon.src = "images/star-regular.png";
            starIcon.dataset.favorites = "false";
            removeFromFavorites(resource);
        }
        else{
            starIcon.src = "images/star-solid.png";
            starIcon.dataset.favorites = "true";
            addToFavorites(resource);
        }
    }

    function createResourceBox(resource){
        const resourceBox = document.createElement("div");
        resourceBox.id = "resource-box";

        const resourceURL = document.createElement("a");
        resourceURL.href = resource.url;
        resourceURL.target = "_blank";

        const resourceName = document.createElement("div");
        resourceName.classList.add("resource-name");
        resourceName.textContent = resource.name;

        resourceURL.appendChild(resourceName)

        const resourceDescription = document.createElement("div");
        resourceDescription.classList.add("resource-description");
        resourceDescription.textContent = resource.description;

        const starIcon = document.createElement("img");
        starIcon.src = "images/star-regular.png";
        starIcon.alt = "favorites_Icon";
        starIcon.classList.add("star-icon");
        starIcon.dataset.favorites = "false";

        resourceBox.appendChild(starIcon)
        resourceBox.appendChild(resourceURL);
        resourceBox.appendChild(resourceDescription);

        starIcon.addEventListener("click", function(){
            toggleFavorites(starIcon, resourceBox);
        })

        return resourceBox;
    }
    
    fetch("/data/studyresource.json")
        .then(function(response){
            return response.json();
        })
        .then(function(jsonData){
            jsonData.sort(function(a,b){
                return a.name.localeCompare(b.name);
            });

            jsonData.forEach(function(resource){
                const box = createResourceBox(resource);
                box.classList.add("custom-box");
                jsonBoxes.appendChild(box);
            });
        })
        .catch(function(error){
            console.error("Error fetching study resource data:", error);
        });

});

2

Answers


  1. When you do resource.cloneNode(true), you create new Nodes, which are no longer related (reference-wise) to resource, even though their content appears the same (they are cloned…).

    Hence the error message when you attempt to remove the original resource from where you actually put its clone instead (favorites.appendChild(clone) but favorites.removeChild(resource)).


    A simple solution could simply be to store a reference of the clone, e.g. alongside the resource directly, so that you can retrieve it to get the Node to be removed:

    function addToFavorites(resource){
      const clone = resource.cloneNode(true);
      favorites.appendChild(clone);
      // Keep a reference to clone alongside resource
      resource.cloneReference = clone;
    }
        
    function removeFromFavorites(resource){
      // Retrieve the clone Node
      const clone = resource.cloneReference;
      favorites.removeChild(clone);
    }
    
    Login or Signup to reply.
  2. The error message "Failed to execute ‘removeChild’ on ‘Node’: The node to be removed is not a child of this node." means that the removeChild() method is being called on a node that does not contain the child node that you are trying to remove.

    In your code, the removeFromFavorites() function is being called with the resource parameter, which is an element from the jsonBoxes NodeList. However, the favorites element is not a child of the jsonBoxes NodeList.

    To fix this error, you need to make sure that the resource element is a child of the favorites element before you call the removeChild() method. You can do this by using the contains() method to check if the favorites element contains the resource element.

    Here is the corrected code:

    function removeFromFavorites(resource){
        if(favorites.contains(resource)){
            favorites.removeChild(resource);
        }
    }
    

    This code first checks if the favorites element contains the resource element. If it does, then the removeChild() method is called to remove the resource element from the favorites element.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search