Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3.js: Passing data from parent to child nodes

I am using d3 to make a stacked bar chart.

The data is an array with one object for each bar (e.g 'likes'). Then each object contains an array of values which drive the individual rectangles per bar:

data =  [{
          key = 'likes', values = [
            {key = 'blue-frog', value = 1}, 
            {key = 'goodbye', value = 2}
          ]
        }, {
          key = 'dislikes, values = [
            {key = 'blue-frog', value = 3},
            {key = 'goodbye', value = 4}
          ]
        }]

The chart is working fine, like so:

// Create canvas
bars = svg.append("g");

// Create individual bars, and append data
// 'likes' are bound to first bar, 'dislikes' to second
bar = bars.selectAll(".bar")
        .data(data)        
        .enter()
        .append("g");

// Create rectangles per bar, and append data
// 'blue-frog' is bound to first rectangle, etc.
rect = bar.selectAll("rect")
        .data(function(d) { return d.values;})
        .enter()
        .append("rect");

I would like to create tooltips per rectangle which say things like "Likes: 2" This involves binding information about the bar keys to the rectangles. I have not found a way to do this (other than changing the data). Can you see an elegant solution?

Also, I'm not sure I have described this question in the best way. Let me know if you have any suggestions for a better title.

like image 667
Derek Hill Avatar asked Dec 01 '12 19:12

Derek Hill


1 Answers

Not sure if you'd consider this an elegant solution, but it avoids changing your data.

It draws on a few key 'features':

  • You are at liberty to get a reference to & then use the selection array (but to use this array you need to know the current selection group - see last point)
  • Through the .parentNode property, you can get the DOM element of the parent node
  • Through the __data__ property, you can get to the associated data of the parent node
  • The data access function function(d,i){....} can be supplied in a 3-parameter form: function(d,i,j){....} where j is the current selection group.

So, in your example, you could get the selection array:

var selection = bar.selectAll("rect")
  .data(function(d) { return d.values;})
  .enter();

From the selection array, you could get at the data in question:

selection
  .append("li")
  .text(function(d,i,j) {
    return selection[j].parentNode.__data__.key; 
  }

Easier to see a full example, rather than code snippets in this case:

http://bl.ocks.org/4199266

As I mention on the gist - I recall reading about this 3-parameter form of the data accessor function, but can't for the life of me remember where - I would welcome being pointed at source material that documents this 'feature'.

like image 184
tsenga Avatar answered Sep 29 '22 07:09

tsenga