I Like
I Like

Reputation: 1847

d3js stacked bar chart not updating

I am experimenting with a stacked bar chart in d3js and ran into enter exit selection difficulties. I used the d3.stack to get two arrays organized by keys, then I tried to follow the general update pattern. The problem I'm having now is the data is not getting updated when I click a different state in the dropdown menu. Here's the problem code and a link to the full project: http://plnkr.co/edit/8N8b2yUYRF9zqRkjkIiO?p=preview

var series = g.append("g")

var seriesready = 
    series.selectAll("g")
    .data(stack(data))
    .enter().append("g")
    .attr("fill",function(d){console.log(d); return z(d.key)}) //not logging 
when I update the bar chart

var rectangles = 
    seriesready.selectAll("rect")
    .data(function(d){return d})

rectangles.exit().remove()

rectangles.enter().append("rect")
      .attr("width", x.bandwidth())
      .transition()
        .duration(1500)
        .attr("transform", function(d) {console.log(d); return "translate(" + x(d.data.Date) + ",0)"; })
        .attr("height", function(d) {
        return height - y(d[1]-d[0]);
      })
        .attr("y", function(d) {
        return y(d[1]-d[0]);
      });

I also think I'm getting confused as to what selections should be removed or added. Would really appreciate any pointers. Data viz is fun to work with, but I still haven't fully grasped data binding yet.

Upvotes: 0

Views: 98

Answers (1)

Eric Guan
Eric Guan

Reputation: 15992

I have not made the switch to version 4 yet, but the data binding methodology is the same i think.

You need to define a key function as the second parameter to the .data() function.

A key function may be specified to control which datum is assigned to which element, replacing the default join-by-index.

https://github.com/d3/d3-selection/blob/master/README.md#selection_data


Your updated code

http://plnkr.co/edit/wwdjJEflZtyACr6w9LiS?p=preview

The changed code:

var seriesUpdate = series.selectAll("g")
        .data(stack(data),d=>d)
var seriesready = seriesUpdate.enter().append("g")
        .attr("fill",function(d){return z(d.key)})

seriesUpdate.exit().remove()

When binding data to elements, D3 calculates what data is new/existing/removed in relation to the selection. By default it does this by data index - the size of the input array. Since the computed stack data for michigan and ohio both return 2 sets of data (injured and killed), D3 views this as "same" data, thus it's an update.

If you define a key function, D3 recognizes the computed stack data for michigan and ohio as being "different" data, thus it's an enter.

With a key function, when you select Ohio first, the enter selection is size 2 with Ohio. If you then select Michigan, the enter selection is size 2 with Michigan, and the exit selection is size 2 with Ohio.

Upvotes: 1

Related Questions