72

Other stack answers such as this and this seem to be specialized cases and I believe my case is more generalized. I am doing this in my js:

var markerDiv = document.createElement("div");
markerDiv.innerHTML = "<div id='MyCoolDiv' style='color: #2b0808'>123</div>";
document.getElementById("playerContainer").appendChild(markerDiv);

// after a brief delay, REMOVE the appended child
setTimeout(function(){ 
    var myCoolDiv = document.getElementById("MyCoolDiv");
    document.getElementById("playerContainer").removeChild(myCoolDiv);
}, 1500);

Everything works correctly and as expected (the div is correctly appended and I can see it) until removeChild() is called, at which time I get the error Failed to execute 'removeChild' on 'Node'.

What am I doing wrong?

Community
  • 1
  • 1
HerrimanCoder
  • 6,835
  • 24
  • 78
  • 158

8 Answers8

41

Your myCoolDiv element isn't a child of the player container. It's a child of the div you created as a wrapper for it (markerDiv in the first part of the code). Which is why it fails, removeChild only removes children, not descendants.

You'd want to remove that wrapper div, or not add it at all.

Here's the "not adding it at all" option:

var markerDiv = document.createElement("div");
markerDiv.innerHTML = "<div id='MyCoolDiv' style='color: #2b0808'>123</div>";
document.getElementById("playerContainer").appendChild(markerDiv.firstChild);
// -------------------------------------------------------------^^^^^^^^^^^

setTimeout(function(){ 
    var myCoolDiv = document.getElementById("MyCoolDiv");
    document.getElementById("playerContainer").removeChild(myCoolDiv);
}, 1500);
<div id="playerContainer"></div>

Or without using the wrapper (although it's quite handy for parsing that HTML):

var myCoolDiv = document.createElement("div");
// Don't reall need this: myCoolDiv.id = "MyCoolDiv";
myCoolDiv.style.color = "#2b0808";
myCoolDiv.appendChild(
  document.createTextNode("123")
);
document.getElementById("playerContainer").appendChild(myCoolDiv);

setTimeout(function(){ 
    // No need for this, we already have it from the above:
    // var myCoolDiv = document.getElementById("MyCoolDiv");
    document.getElementById("playerContainer").removeChild(myCoolDiv);
}, 1500);
<div id="playerContainer"></div>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
25

For me, a hint to wrap the troubled element in another HTML tag helped. However I also needed to add a key to that HTML tag. For example:

// Didn't work
<div>
     <TroubledComponent/>
</div>

// Worked
<div key='uniqueKey'>
     <TroubledComponent/>
</div>
dlchang
  • 917
  • 10
  • 14
  • 2
    Wow, I'm surprised adding a key was all that was needed! Brilliant! – gignu Feb 02 '23 at 16:24
  • cool, this worked for me, but can you explain why its needed :) – Mohsin Amjad Apr 05 '23 at 17:03
  • I had a component `LoginCheck`, which caused the issue, simply wrapping it in a `
    ` in the *parent* component removed the error for me. I didn't need a `key`. But thanks for pointing me in the right direction.
    – Peter Ilfrich Apr 13 '23 at 02:29
  • simply adding a `key` with a mundane value as in `key={0}` worked like a charm in my case. In my particular case I think the offending library was `ag-grid` for React. In the end, the code that worked was: `return ;`. – Marcus Junius Brutus Aug 03 '23 at 18:27
6

The direct parent of your child is markerDiv, so you should call remove from markerDiv as so:

markerDiv.removeChild(myCoolDiv);

Alternatively, you may want to remove markerNode. Since that node was appended directly to videoContainer, it can be removed with:

document.getElementById("playerContainer").removeChild(markerDiv);

Now, the easiest general way to remove a node, if you are absolutely confident that you did insert it into the DOM, is this:

markerDiv.parentNode.removeChild(markerDiv);

This works for any node (just replace markerDiv with a different node), and finds the parent of the node directly in order to call remove from it. If you are unsure if you added it, double check if the parentNode is non-null before calling removeChild.

Anish Goyal
  • 2,799
  • 12
  • 17
6

I was wraped it with <> </> as a parent when I changed it to normal , div , its worked fine

ahmed mersal
  • 167
  • 2
  • 3
3

As others have mentioned, myCoolDiv is a child of markerDiv not playerContainer. If you want to remove myCoolDiv but keep markerDiv for some reason you can do the following

myCoolDiv.parentNode.removeChild(myCoolDiv);

JSFiddle

xort
  • 337
  • 2
  • 12
1

I'd a similar problem in the vue.js project. Then, I got a hint on changing the fragment wrapper to an HTML element. The most common use case for fragments is probably when you need to return multiple elements. With fragments this is easy and you don't need your typical wrapper div for the elements. Its short syntax is <></>.

Basically, I used the fragment pattern in Vue then I got the above error rendering the component dynamically using transition. It appears that the dynamic component(which entails multiple elements) needed to be wrapped with an HTML element, not a fragment.

// Vuejs
<transition
  name="router-anim"
  enter-active-class="animated animated-enter"
  mode="out-in"
  leave-active-class="animated animated-exit"
>
  <router-view /> // dynamic rendering based on current route using vue-router
</transition>
Akolade Adesanmi
  • 1,152
  • 11
  • 15
0

In next.js 13, if you are using app directory and forget to put <html> and <body> open close tags in app/layout.tsx file you might see this error as well.

SayJeyHi
  • 1,559
  • 4
  • 19
  • 39
0

Make sure you are not duplicating elements in single file .For example: you have page-one.js which has <body> </body> element in it and you imported a component named component-one.js which also has <body> </body> in it. This will produce the error you are asking for. This applies to all main elements : <header>, <main>, <footer>, <body>, <html> . Make sure these elements are not duplicating after getting components imported. Child elements like <div> and others donot give these errors.

Biolo Account
  • 196
  • 2
  • 6