This website is not current and will be retired at some point. See About for latest.
These tutorials address an older version of D3 (3.x) and will no longer be updated. See my book Interactive Data Visualization for the Web, 2nd Ed. to learn all about the current version of D3 (4.x).
D3 smartly employs a technique called chain syntax, which you may recognize from jQuery. By “chaining” methods together with periods, you can perform several actions in a single line of code. It can be fast and easy, but it’s important to understand how it works, to save yourself hours of debugging headaches later.
By the way, functions and methods are just two different words for the same concept: a chunk of code that accepts an argument as input, performs some action, and returns some data as output.
Let’s revisit our first line of D3 code (demo page here).
d3.select("body").append("p").text("New paragraph!");
This may look like a big mess, especially if you’re new to programming. So the first thing to know is that JavaScript, like HTML, doesn’t care about whitespace and line breaks, so you can put each method on its own line for legibility:
d3.select("body")
.append("p")
.text("New paragraph!");
Everyone has their own coding style. Use whatever indents, line breaks, and whitespace (tabs or spaces) works for you.
Let’s deconstruct each piece of this code.
d3
— References the D3 object, so we can access its methods.
.select("body")
— Give select()
a CSS selector as input, and it will return a reference to the first element in the DOM that matches. (Use selectAll()
when you need more than one element.) In this case, we just want the body
, so a reference to body
is handed off to the next method in our chain.
.append("p")
— append()
creates whatever new DOM element you specify and appends it to the end (but just inside) of whatever selection it’s acting on. In our case, we want to create a new p
within the body
. We specified "p"
as the input argument, but this method also sees the reference to body
that was passed down the chain from the select()
method. Finally, append()
, in turn, hands down a reference to the new element it just created.
.text("New paragraph!")
— text()
takes a string and inserts it between the opening and closing tags of the current selection. Since the previous method passed down a reference to our new p
, this code just inserts the new text between <p>
and </p>
. (In cases where there is existing content, it will be overwritten.)
;
— The all-important semicolon indicates the end of this line of code.
Many, but not all, D3 methods return a selection (or, really, reference to a selection), which enables this handy technique of method chaining. Typically, a method returns a reference to the element that it just acted upon, but not always.
So remember: When chaining methods, order matters. The output type of one method has to match the input type expected by the next method in the chain. If adjacent inputs and outputs are mismatched, the hand-off will function more like a dropped baton in a middle-school relay race.
When sussing out what each function expects and returns, the API reference is your friend. It contains detailed information on each method, including whether or not it returns a selection.
Our sample code could be rewritten without chain syntax as:
var body = d3.select("body");
var p = body.append("p");
p.text("New paragraph!");
Ugh! What a mess. Yet there will be times you need to break the chain, such as when you are calling so many functions that it doesn't make sense to string them all together. Or just because you want to organize your code in a way that makes more sense to you.
Next up: Binding data →
These tutorials address an older version of D3 (3.x). See my book Interactive Data Visualization for the Web, 2nd Ed. to learn all about the current version of D3 (4.x).
Download the sample code files and sign up to receive updates by email. Follow me on Twitter for other updates.
These tutorials have been generously translated to Catalan (Català) by Joan Prim, Chinese (简体中文) by Wentao Wang, French (Français) by Sylvain Kieffer, Japanese (日本語版) by Hideharu Sakai, Russian (русский) by Sergey Ivanov, and Spanish (Español) by Gabriel Coch.