user2259146
user2259146

Reputation: 269

D3 update values to a new dataset on mouse click

All, I am having difficulty updating the values of some circles I have drawn with D3. Entire code is below.

You will see that there are 3 values in dataset1 and 4 values in dataset2.

All I simply want to do is update the circles on a mouse click of a button from dataset1 to dataset2.

However when I run this code, only the first three values of dataset2 are updated, the fourth value is missing. this must be something to do with the fact that dataset1 only have 3 values and therefore only updating the first 3 values in dataset2.

Appreciate a response which tells me exactly what I need to do not just something like, do update or something. I have searched a lot but most responses are vague.

Very grateful for your help.

    <html>
<head>
    <script type="text/javascript" src="d3/d3.js"> </script>
    <title>update data</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
 <p id = "h">test</p>   
 <button onclick="fader()">Click me</button> 
<script>    



var dataset1 = [30,90,150];
 var dataset2 = [5,30,100,79];

 d3.selectAll("#h") 
.append("svg")
.attr("width",200)
.attr("height",200)

.selectAll("circle")
.attr("id","mastercircle")        
.append("svg")
.data(dataset1)
.enter()
.append("circle")
.attr("id","mycircle")      
.attr("cy", 90)
.attr("cx", String)
.attr("r", Math.sqrt)
.attr("fill","green")


 .style("opacity", 1)
 .transition().duration(600) 
 .style("opacity", 0.5)    
    ;

   function fader() {


      d3.selectAll("#mycircle")

        .data(dataset2) 

    .attr("cy", 90)
    .attr("cx", String)
    .attr("r", Math.sqrt)
    .attr("fill","red")
    .style("opacity", 1)
    .transition().duration(1000)
     .style("opacity", 0.5)     

    ;

    };


   </script>


</body>
 </html>

See code after fully expanding the FIDDLE code. It now adds the new data but doesn't remove the old data. Grateful if you can tell me where I need to exit and remove?

Just trying to learn exactly what is going on without using variables to understand what D3 is actually doing.

    <html>
    <head>
        <script type="text/javascript" src="d3/d3.js"> </script>
        <title>Delete</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
     <p id = "h">test</p>   
       <button id = "update">Click me</button> 
<script>    



var dataset1 = [30, 90, 150];
var dataset2 = [5, 30, 100, 79];

 d3.select("#h") //p must be loaded for this to work i.e. above the code
    .append("svg")
    .attr("width",200)
    .attr("height",200)

    .selectAll("circle")
    .data(dataset1)

 //sel above

    .enter()
    .append("circle")
    .attr("class","circles")


    .attr("cy", 90)
    .attr("cx", String)
    .attr("r", Math.sqrt)
    .attr("fill","green")    
    .style("opacity", 1)
    .transition().duration(600)
    .style("opacity", 0.5)    
    ;

function fader() {


d3.select("#h") 

.append("svg")
    .attr("width",200)
    .attr("height",200)
    //.selectAll("circle")
    //.data(dataset1)
    .selectAll(".circles")  
    .data(dataset2)



      .enter() // enter selection
      .append("circle")
        .attr("class", "circles")

      //update selection
        .transition().duration(1000)
        .attr("cy", 90) 
        .attr("cx", String)
        .attr("r", Math.sqrt)
        .attr("fill", "red")
        .style("opacity", 1)     
        .style("opacity", 0.5)    ;

};

d3.select("#update").on("click", fader);



</script>


    </body>
</html>

Upvotes: 2

Views: 970

Answers (1)

FernOfTheAndes
FernOfTheAndes

Reputation: 5015

There are lots of resources on understanding the enter/update/exit pattern, and one of the most popular is Thinking with Joins by the creator of D3.

I have applied this important pattern to your code and placed it in this FIDDLE. You can look at the code (with key comments) and compare to the explanations in Mike's post.

sel 
    .enter() // enter selection
    .append("circle")
    .attr("class", "circles");

sel //update selection
    .attr("cy", 90)
    .attr("cx", String)
    ...

NOTE: one commonly overlooked aspect is the importance of giving a specific class to the elements you draw so that you can refer to them by this class when you want to update them or handle them in any other way (class circles in the code). I also moved the second transition to an earlier point so that you can clearly see the new circle being added to the group, and in the correct position.

Upvotes: 3

Related Questions