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:
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:
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'
As I understand it, when you run data()
with a key function, it does the following:
data()
on.data()
as the first argument.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With