What is the difference D3 datum vs. data?
I found the correct answer here from Mike himself:
D3 - how to deal with JSON data structures?
If you want to bind your data to a single SVG element, use
(...).data([data])
or
(...).datum(data)
If you want to bind your data to multiple SVG elements
(...).data(data).enter().append("svg")
.....
After having looked into this a bit, I've found that the answers here on SO are not complete as they only cover the case when you invoke selection.data
and selection.datum
with an input data
parameter. Even in that scenario, the two behave differently if the selection is a single element versus when it contains multiple elements. Moreover, both of these methods can also be invoked without any input arguments in order to query the bound data/datum in the selection, in which case they once again behave differently and return different things.
Edit - I posted a slightly more detailed answer to this question here, but the post below pretty much captures all the key points regarding the two methods and how they differ from each other.
When supplying data
as an input argument
selection.data(data)
will attempt to perform a data-join between the elements of thedata
array with the selection resulting in the creation ofenter()
,exit()
andupdate()
selections that you can subsequently operate on. The end result of this is if you pass in an arraydata = [1,2,3]
, an attempt is made to join each individual data element (i.e. datum) with the selection. Each element of the selection will only have a single datum element ofdata
bound to it.selection.datum(data)
bypasses the data-join process altogether. This simply assigns the entirety ofdata
to all elements in the selection as a whole without splitting it up as in the case of data-joins. So if you want to bind an entire arraydata = [1, 2, 3]
to every DOM element in yourselection
, thenselection.datum(data)
will achieve this.
Warning: Many people believe that
selection.datum(data)
is equivalent toselection.data([data])
but this is only true ifselection
contains a single element. Ifselection
contains multiple DOM elements, thenselection.datum(data)
will bind the entirety ofdata
to every single element in the selection. In contrast,selection.data([data])
only binds the entirety ofdata
to the first element inselection
. This is consistent with the data-join behavior ofselection.data
.
When supplying no data
input argument
selection.data()
will take the bound datum for each element in the selection and combine them into an array that is returned. So, if yourselection
includes 3 DOM elements with the data"a"
,"b"
and"c"
bound to each respectively,selection.data()
returns["a", "b", "c"]
. It is important to note that ifselection
is a single element with (by way of example) the datum"a"
bound to it, thenselection.data()
will return["a"]
and not"a"
as some may expect.selection.datum()
only makes sense for a single selection as it is defined as returning the datum bound to the first element of the selection. So in the example above with the selection consisting of DOM elements with bound datum of"a"
,"b"
and"c"
,selection.datum()
would simply return"a"
.
Note that even if
selection
has a single element,selection.datum()
andselection.data()
return different values. The former returns the bound datum for the selection ("a"
in the example above) whereas the latter returns the bound datum within an array (["a"]
in the example above).
Hopefully this helps clarify how selection.data
and selection.datum()
differ from each other both when providing data as an input argument and when querying for the bound datum by not providing any input arguments.
PS - The best way to understand how this works is to start with a blank HTML document in Chrome and to open up the console and try adding a few elements to the document and then start binding data using selection.data
and selection.datum
. Sometimes, it's a lot easier to "grok" something by doing than by reading.