Giordano Giordano -4 years ago 170
jQuery Question

d3.js - Multiple line chart doesn't update circles

I'm working on a d3 chart (Multiple line chart).

I'm trying to represent a stock prediction, so basically the chart contains two lines: stock values line and an other one for my prediction.

The prediction is monthly, all days of month are represented in the chart.

In order to choose the month I have added a dropdown menu.

I appended a circle on each daily data, and works well for the first time. When user tries to change the month, the old circles are not updated, but the new ones are added.

Follow the code about circles:

topicEnter.append("g").selectAll("circle")
.data(function(d){return d.values})
.enter()
.append("circle")
.attr("r", 5)
.attr("cx", function(dd){return x(dd.date)})
.attr("cy", function(dd){return y(dd.probability)})
.attr("fill", "none")
.attr("stroke", "black");


I have done a fiddle to understand better the situation and in order to show code.

What am I missing here? Why don't the circles update themself with the lines?

Answer Source

The problem is your update cycle, but there are a good number of examples of the enter, update, exit process in d3.

But essentially:

  1. You append a new g element for each batch of circles, which means you have an empty selection (no circles are in that g yet) each time and each data point is appended (and none are removed). You don't need this extra append. Take a look at the DOM structure on each append in your existing code.

  2. Your enter() selection returns new elements - not modified elements. So if your total number of elements remains the same you will have an empty enter() selection. You'll want to update existing elements separately (alternatively, remove them all and append them all every time).

You'll want something closer to this:

// set the data
   circles =  topic.selectAll("circle")
      .data(function(d){return d.values});
// update existing circles      
   circles.attr("cx", function(dd){return x(dd.date)})
      .attr("cy", function(dd){return y(dd.probability)});
// add new circles     
   circles.enter()
      .append("circle")
      .attr("r", 5)
      .attr("cx", function(dd){return x(dd.date)})
      .attr("cy", function(dd){return y(dd.probability)})
      .attr("fill", "none")
      .attr("stroke", "black");
   // remove excess circles   
   circles.exit().remove();

You'll likely also want to revise the lines that append the lines to reflect the enter, update, exit cycle in d3.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download