It’s time to live up to D3’s true name and potential by integrating some real data into your visualization. This lesson introduces the fundamental concepts of enter, update, and exit selections, topics essential for being successful with D3.
[00:01] The name D3 is actually a shorthand for Data-Driven Documents, so let's look at how we integrate data into our visualizations.
[00:08] I've updated our HTML file here for this example, and you'll notice that all we have in our body is an empty div here with the class of chart, and then our script tag is still being included. I've got a basic style up here to size and color our chart container. You see that here in the page.
[00:28] If we look at our app.js file, you can see that I've got a simple five-element array here of five simple objects that have a name and a score property. We've got these names that start with A, B, C, D, E, just so we have some implicit ordering there and a basic score that we'll assume is on a scale of 100.
[00:51] The first thing we need to do to integrate our data is we need to start with a selection. We're going to say D3.select.chart, since we're using that CSS class as our selector query, and then we're going to do select.All(div) to select all of the divs within that chart.
[01:11] You know from looking at this file that there are no divs within the chart div, but we'll get to that. Now that we have a selection representing all the divs inside of our container, we can then say .data, and pass in our scores array.
[01:26] What we've now done is create a data join, and before we go too much further, I want to look at a graphic that Mike Bostock, the creator of D3, has put together to explain data joins.
[01:38] You can see here, a simple Venn diagram, where the first circle represents our data, and the second circle represents our DOM elements. You can see here, this first section, where we've got data, but no DOM elements, is what's referred to as the enter selection.
[01:56] Where we have both data and elements is referred to as the update selection, and where we only have elements but no data is our exit selection. If we switch back to our page here and think about what we've done, we have told D3 to select all of the divs within the chart div, and then merge the data with that selection.
[02:20] Since there were no divs in there that means that we don't have any elements, and we only have data.
[02:27] What we have resulting from this data join is five elements in the enter selection, which is just data and no elements, and an empty update selection, and an empty exit selection. By default, a data join like this returns the update selection, so let's go ahead and assign this to a variable called update.
[02:46] To access the enter selection, we'll use the .enter method on the update selection. Now that we have this enter selection, we need to actually create the elements, since we're just dealing with data and no elements here.
[02:59] We're going to say update .enter.append(div), and this will tell D3 we want to create an append a div for everything in our data that doesn't already have a DOM element.
[03:12] Now that we've created an append at a div, we need to populate it with something, so let's go ahead and set its text. We'll do that by calling the text method and giving it a function, and that function is going to receive each data element as its first argument, which we'll call D. That's a convention in D3 that you'll see all the time.
[03:33] D represents the data element, and so then we're just going to return the name property from that data object. If we save that, we can see that we do now have all of those divs created and populated with the name.
[03:47] If we go inspect this, we can see that we do, in fact, have divs that have been created and added to the parent chart div. We can also style these divs, so let's go ahead and color them green just to represent that they're being created by this data join.
[04:04] Before we move on, I want to talk about this update selection a little bit. The reason it's called the update selection, because this is for when you already have elements on the page, and some of the data corresponds to those items.
[04:19] This is generally going to happen when the data is updated, rather than rendered for the first time, so if you have data that's changing over time, you're not going to recreate the entire chart and build everything from scratch. Some of your elements are just going to be getting updated.
[04:35] To see this in action, we'll go over to our chart here, and create a couple of divs. We're going to say, "Billy and Cindy are already on the page." You'll notice that this results in some weirdness in our output, but that just means that we need to update our code to handle this properly.
[04:57] When you call the data method to do your data join, there's an optional second parameter which is known as the key function. The key function is used for mapping data items to DOM elements.
[05:09] In our case, we need to map the name property to the inner text of the div, so we're going to pass this function that, again, accepts a parameter named D, representing the data item, and we're going to check and make sure that that item exists.
[05:25] If it does, we'll return the name. If it does not, we've already got an element. We're going to return the inner text. D3 will use this to merge these things together and know what's already existing and what is not.
[05:41] You'll notice that we're actually using this to access the DOM element itself. In a lot of places in D3, when you've got these functions that are being used to set data, the this context will be set to the DOM element.
[05:57] Just for the sake of clarity, let's style the items that are already here that are not being created and we'll turn their color blue. Now we can see that Billy and Cindy are being updated by our code, and Alice, David, and Emily are being created by our code.
[06:15] The last part of that graphic that we saw was the exit selection, which represents items that are already on the DOM, but don't have any corresponding data. To demonstrate that, we'll go ahead and make a new div here by default, we'll put Walter in there.
[06:36] We now see that Walter is on the page. He's in a random spot because we're not handling that at all. What we need to do now is go over here, and again, we access the exit selection as a method on the update selection. We'll say update.exit. In this case, we just want to remove it.
[06:56] If we save that, we can now see that Walter, in fact, gets removed from the page. The last thing I want to look at is something that's actually changed in version four of D3, and that's how you write code to affect all of the items that are still on the chart, so both the update selection and the enter selection.
[07:15] What we're going to do is we'll create a variable to hold this enter selection, and we'll call it enter. Now we have this variable, update, which is holding our update selection, and enter, which is holding our enter selection.
[07:29] Now if we go down here and we say update.merge and pass in enter, just to make sure we've got the right selection here, we can say style text transform is uppercase, we can see that all of those things are affected.
[07:45] We've got our blue items from our update selection, and our green items from our enter selection, and we're then affecting both of them by merging those two selections together. What we actually want to do, though, is give these items some dimension.
[08:00] We'll say height is 50 pixels, and then we'll give them a border and some background color. I skipped over the width, because I wanted to return to that. We're going to say style width. In this case, we're going to use the data again, but this time to size it.
[08:17] We'll return the score property off of our data object, tack on the px suffix, and now if we save it, you can see we get these sized boxes based on the data. Alice and David have the largest scores. You can see their boxes are the widest. Billy had the lowest score, so his is the smallest. Now we're creating a data visualization.
Heyy-- Could you share the link to Mike Bostock's article that explains data joins- the one with the venn diagrams? I'm curious to get more background on his approach/ way of framing enter/exit/etc.
Actually nevermind, I googled and found: https://bost.ocks.org/mike/join/ :)
Actually nevermind, I googled and found: https://bost.ocks.org/mike/join/ :)
What I didn't understand was this - at 2:27 you were saying: <br> <br> "What we have resulting from this data join is five elements in the enter selection, which is just data and no elements, and an empty update selection, and an empty exit selection. By default, a data join like this returns the update selection, so let's go ahead and assign this to a variable called update." <br> <br> According to diagram and the text above, the resulting selection should return enter selection - because it is "data and no elements". But you are saying that data joint like this returns the "update" selection. <br> <br> Yes, I know, later on you are referring to this topic saying: <br> <br> "The reason it's called the update selection, because this is for when you already have elements on the page, and some of the data corresponds to those items." <br> <br> But it is still confusing - because in the example there are NO elements, and even if there were some elements, what if there are only 3 of them but 5 data elements - now we have enter and update selection together. I am struggling a little bit with this.
@Doug, .data() will return always a subclass with three properties: _enter, _exit, and _groups, corresponding to the so-called "update" selection, wrapped together with all the methods you need attached to the subclass prototype. So ya, I guess @Ben is maybe cutting too short by saying that a data join like that returns an update selection by default.
So those three are always there. When you join data points that have not matching elements in the DOM, placeholders are created in the _enter selection. When there are no more data points for existing DOM elements, those are found in the _exit property. When data changes for an already matched element, you'll find a reference to those DOM elements in the _groups selection.
You can explore the
update variable by yourself by logging it to the console and playing with it until it clicks.
I agree though, not the most straightforward concept to get ^_^
Something probably changed since this is a pretty old tutorial. The second argument to the data method (the function) doesn't seem to return either, but instead keeps the original div inside the html and then adds the other 5 entries from our data array.
Still works, but different.