DOMException: Failed to execute 'insertBefore' on 'Node': The new child element contains the parent.

I am getting DOMException: Failed to execute 'insertBefore' on 'Node': The new child element contains the parent. with this
notebook

If I only bound a single level by commenting out the following, it works as desired

/*const outerTwo = outerOne.selectAll("div");

outerTwo.exit().remove();

outerTwo
  .data(outerTwoData)
  .join("xhtml:div")
  .attr("id", (_, i) => `outerTwo${i}`);*/

But I intend d3 to give me the following structure in DOM

    doc
	├── <div id='viz'>
	│   └── <div id='outer0'>
	│       ├── <div id='inner0'>
	│       ├── <div id='outer1'>
	│       ├──  <div id='outer2'>
	│   └── <div id='outer1'>	
	│       ├── <div id='inner0'>		
	│       ├── ...so on and so forth

Never use global selectors in notebooks:

const div = d3.select("div");

You probably meant to write

const div = d3.create("div");

instead?

Can you say more about your intentions behind timer? I guess the idea here is that you want to add each child one by one?

@mootari The goal here is to be able to append the children to the parent which is of the same kind
such as divOuter>divInner or with svg <g> element gOuter>gInner

I am able to solve it with a selection like this

const div = d3.select('#viz');

const t = d3.timer((e) => {
  const outerOneData = d3.range(0,5);
  const outerTwoData = d3.range(0,3);
  
  const outerOne = div.selectAll('.outerOne');
  
  outerOne.exit().remove();
  
  outerOne.data(outerOneData)
	.join('xhtml:div')
	.classed('outerOne', true)
	.attr('id',(_,i)=>`outer${i}`)   
	
 const outerTwo = outerOne.selectAll('.outerTwo');  
  
   outerTwo.exit().remove();
   
   outerTwo      
	.data(outerTwoData)
	.join('xhtml:div')
	.classed('outerTwo', true)
	.attr('id',(_,i)=>`outerTwo${i}`);  

  
  if (e > 200) t.stop();
}, 150);

Your proposed solution appears to be taken exactly from the response to your identical question posted at the same time on StackOverflow. I don’t necessarily think that cross-posting is such a bad thing but I do think that, if you’re going to post to multiple forums then it’s reasonable to ensure that the questions are properly scoped. If, for example, you’re working with D3 in a webpage outside of the Observable notebook environment, then it’s probably worth placing it in the D3 category and I don’t think it makes sense to include an Observable notebook that doesn’t appear to attempt to adhere to notebook conventions.

To mootari’s point on global selectors, you should realize that the two selectors that you use

d3.select("div")

and

d3.select('#viz')

Are very different. The second one, from the proposed solution, is much more specific as it selects the element with id “viz”; there should be just one of those. The first one selects by element type and, generally, there might be a lot of DIVs. For that reason, it’s probably not a good idea to select by element type in any environment, Observable or not.

@mcmcclur I apologize for cross-posting as I was struggling with the issue on my own for a few days; I wanted to come to a solution as I need to implement this on a prod element. I wanted this to be resolved quickly and different forums provide different ideas as I have experienced in the past (not necessarily, on this very question).

I understnad this now.

Also, for all d3 questions, moving forward, I will place them in d3 Category as you suggested. This is an amazing forum and it has helped me tremendously with my d3 learning. Because I don’t use an observable notebook for my prod material, I don’t know all the best practices and stick to them. I only utilize a notebook for all dev materials important to me or just to ask questions in the forum. Unlike stack, there is no code snippet here; the equivalent is the notebook with best practices which I don’t have a tight grip on.

Again, I am sorry. Also, I just shared the solution from stack so that @mootari knows what I was actually up to and not to claim any credits or anything whatsover.

1 Like