简体   繁体   中英

Why does D3 not insert elements inside the selected element, when using data().enter()?

I'm doing a bit of messing around with D3 (v7) and noticed something odd while working with inserting elements inside another element.

Here is what's happening: Inside the body tag, I have a single div element

<div id='graph'></div>

In my JS, which is called upon loading the body, I have three commands:

 // declare a sample array var dataset = [5, 10, 15, 20, 25] // 1) Insert the contents of 'dataset' in a <p> inside #graph d3.select("#graph").insert('p').text(dataset) // 2) Insert a <div> with the class 'block' inside #graph d3.select("#graph") .insert("div") .attr("class", "block") // 3) Insert one <div> per each element inside 'dataset' with the class 'block' inside #graph d3.select("#graph") .data(dataset) .enter() .insert("div") .attr("class", "block")

The way I understand it, each of the three sentences above should create elements inside #graph. However, for some reason, the third command is inserting the 4 div.block outside the body element, like so:

 <body> <div id="graph"> <p>5,10,15,20,25</p> <div class="block"></div> </div> </body> <div class="block"></div> <div class="block"></div> <div class="block"></div> <div class="block"></div>

I'm not sure why the divs in the third sentence are being appended after instead of inside #graph even though I'm doing d3.select("#graph") at the beginning of the command. I think I might be missing another command after .data().enter()

Why are the divs being inserted after ? and How can I make it so that these divs are created inside #graph instead?

You need to specify to what you are appending things: you need to select the container and then select the elements you wish to add/remove/update:

d3.select("#graph")
    .selectAll("div")
    .data(dataset)
    .enter()
    .insert("div")
    .attr("class", "block")

Without specifying a container, you are using the document as the parent, while the first datum will be bound to the selected div (#graph) the rest of the data will be bound to new divs appended to the document ( not the body ), hence why they appear where the do.

The snippet below adopts your code with that change (and some text to indicate whether the div is updated or entered):

 // declare a sample array var dataset = [5, 10, 15, 20, 25] // 1) Insert the contents of 'dataset' in a <p> inside #graph d3.select("#graph").insert('p').text(dataset) // 2) Insert a <div> with the class 'block' inside #graph d3.select("#graph") .insert("div") .attr("class", "block") // 3) Insert one <div> per each element inside 'dataset' with the class 'block' inside #graph var selection = d3.select("#graph") .selectAll("div") .data(dataset); selection.enter().insert("div") .attr("class", "block") .text(d=>"entered:" + d); selection.text(d=>"updated:" + d);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <div id='graph'></div>

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