Javascript – Understanding how D3.js binds data to nodes

d3.jshtml-tablejavascript

I'm reading through the D3.js documentation, and am finding it hard to understand the selection.data method from the documentation.

This is the example code given in the documentation:

var matrix = [
  [11975,  5871, 8916, 2868],
  [ 1951, 10048, 2060, 6171],
  [ 8010, 16145, 8090, 8045],
  [ 1013,   990,  940, 6907]
];

var tr = d3.select("body").append("table").selectAll("tr")
    .data(matrix)
  .enter().append("tr");

var td = tr.selectAll("td")
    .data(function(d) { return d; })
  .enter().append("td")
    .text(function(d) { return d; });

I understand most of this, but what is going on with the .data(function(d) { return d; }) section of the var td statement?

My best guess is as follows:

  • The var tr statement has bound a four-element array to each tr node
  • The var td statement then uses that four-element array as its data, somehow

But how does .data(function(d) { return d; }) actually get that data, and what does it return?

Best Solution

When you write:

….data(someArray).enter().append('foo');

D3 creates a bunch of <foo> elements, one for each entry in the array. More importantly, it also associates the data for each entry in the array with that DOM element, as a __data__ property.

Try this:

var data = [ {msg:"Hello",cats:42}, {msg:"World",cats:17} ]; 
d3.select("body").selectAll("q").data(data).enter().append("q");
console.log( document.querySelector('q').__data__ );

What you will see (in the console) is the object {msg:"Hello",cats:42}, since that was associated with the first created q element.

If you later do:

d3.selectAll('q').data(function(d){
  // stuff
});

the value of d turns out to be that __data__ property. (At this point it's up to you to ensure that you replace // stuff with code that returns a new array of values.)

Here's another example showing the data bound to the HTML element and the ability to re-bind subsets of data on lower elements:

  no description