Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3 .data key initially comes back undefined

I am trying to use the optional key function when binding data in d3. I have a local test data set and I am trying to use the "title" property of each object as the key.

The key function seems to be running 4 times when I only have 3 objects in my data array. In the d3 documentation is says that the data key function may be called multiple times when binding the data, I just don't understand what I am doing wrong.

This is my object and a few lines of code (I am using 'console.log(i)' to illustrate my confusion):

test:[
  {
    "desc":"This it the first test description text.",
    "image":"test1.jpg",
    "title":"Test Project 1"
  },
  {
    "desc":"This is the second test decription text.",
    "image":"test2.jpg",
    "title":"Test Project 2"
  },
  {
    "desc":"This is the third test decription text.",
    "image":"test3.jpg",
    "title":"Test Project 3"
  }
]  

console.log(obj.testJSON.test[0].title);   //line 178
console.log(obj.testJSON.test);   //line 179

d3.selectAll(".slider-image")
 .data(obj.testJSON.test, function(d,i) {console.log(i); return d; });   //line 182

That gives me this output in the console:

console output of d3.key

When trying to console.log 'd' instead of 'i':

 .data(obj.testJSON.test, function(d,i) {console.log(d); return d; });   //line 182

the first log is undefined:

enter image description here

When I try to actually set the key how I think it should be:

  d3.selectAll(".slider-image")
   .data(obj.testJSON.test, function(d) {return d.title; });
  }

I get a type error on the first call to the key function:

 'Uncaught TypeError: Cannot read property 'title' of undefined'
like image 424
haydenwagner Avatar asked Mar 15 '23 22:03

haydenwagner


1 Answers

As I understand it, when you run data() with a key function, it does the following:

  1. Runs the key function on each of the nodes in the selection you're calling data() on.
  2. Runs the key function on each of the data values that you passed to data() as the first argument.
  3. Matches up the results. Nodes in the original selection without a match in the data values become part of the exit() selection (because you often want to get rid of them). Data values that don't match any of the nodes in the original selection go into the enter() selection (because you need to create nodes for them if you want to do anything with them). Data values that match up nodes in the original selection are bound to those nodes, which are placed in the update() selection.

In order for this to work, you need key to be a function that will work on both the nodes in the original selection and on your new data values.

My guess as to what's going on is that d3.selectAll(".slider-image") is either empty, or only contains a node that doesn't have any data bound to it previously. So the key function gets run on it, returns undefined, and then gets run on each of your incoming data values. When you ask for the title attribute of of the original selection's data, it throws an error, because it doesn't have any data. It's probably hard to use a key function effectively if your selection doesn't currently have any data bound to it (although you could maybe do something with indices), so I'm guessing your use case isn't what the key function was intended for.

like image 159
seaotternerd Avatar answered Mar 24 '23 00:03

seaotternerd