I am updating a D3 bar graph in combination with AngularJS. In this case, all data is initially visible, and updates filter out unwanted data. In the past, it worked without problems using this model:
data = [{ name: John Doe, splits: [{distance: 1, time: 1234},] },...]
Now I'm trying to add another panel to each stack using this model:
data = [{ name: John Doe time: 12345, splits: [{distance: 1, time: 1234},] },...]
My problem is updating the data. My calculated values are recalculated correctly, for example, the domain for scaling. The line for updating time still only recognizes data values before updating (the code fragment is greatly truncated for brevity):
// Set ranges of values in axes x.domain(data.map(function(d) { return d.name})); y.domain([ min , max]); // Y Axis is updated to the correct time range chart.append('g').attr('class', 'y axis').call(yAxis).selectAll('text').style('font-family','Open Sans').style('font-size', '.9rem'); // data join / Select Athlete var athlete = chart.selectAll(".athlete").data(data), athdata = athlete.enter(), console.log(data) // data is correct here // add container for each athlete athplace = athdata.append("g") .attr("class", "athlete") .attr("transform", function(d) { return "translate(" + x(d.name) + ",0)"; }) .text(function(d) { return d.name}), // ENTER time athplace.append('rect') .attr('class', "time") .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.time.time); }) .attr("height", 0).transition().duration(300) .attr("height", function(d) { return height-y(d.time); }); ... enter splits & labels // exit splits & athlete splitlabels.exit().transition().duration(300).attr('opacity', 0).remove(); splits.exit().transition().duration(300).attr('height', 0).attr('opacity', 0).remove(); athlete.exit().transition().duration(300).attr('width',0).attr('opacity', 0).remove(); console.log(athlete) // data is still correct // UPDATE time, this chain has the problem with data not being updated. "d" is equal to previous values athlete.selectAll('rect.time') .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.time.time); }) .attr("height", function(d) { return height-y(d.time); });
Due to these errors, the updated columns present incorrect data and create incorrect visualization. I watched / tested all this time, trying to isolate the problem to what I have now. Can someone more experienced with D3 give me some insight?
Note: for those who are interested, this is all in the Angular directive, where I $watch to change the data values, although I am 100% sure that this is not a problem.
Edit
Here is a JSFiddle that shows the same error as in my script. All code was extracted directly from a script demonstrating the problem. Updating the interval at the bottom imitates the replacement of data that usually occurs.