Skip to content

D3.js - Selection API

Selections are a cornerstone of D3.js, allowing you to select DOM elements and apply data-driven transformations. With selections, you can set attributes, styles, properties, HTML content, or text content, and manage data joins. This chapter delves into the D3 Selection API.

The Selection API is part of the core D3 library. You can use it by including the full D3 bundle or the standalone d3-selection module.

<!-- Option 1: Include the full D3 library -->
<script src="https://d3js.org/d3.v7.min.js"></script>
<!-- Option 2: Include the standalone d3-selection module -->
<!-- <script src="https://d3js.org/d3-selection.v3.min.js"></script> -->
<script>
// Example usage:
// const bodySelection = d3.select("body");
// const allParagraphs = d3.selectAll("p");
</script>

These are some of the most fundamental methods in the D3 Selection API:

  • d3.select(selectorOrNode) − Selects the first DOM element that matches the CSS selector string. If selectorOrNode is a node, it wraps the node in a selection.
  • d3.selectAll(selectorOrNodes) − Selects all DOM elements that match the CSS selector string. If selectorOrNodes is an array of nodes, it wraps them in a selection.
  • selection.select(selector) − For each selected element, selects the first descendant element that matches the specified selector.
  • selection.selectAll(selector) − For each selected element, selects all descendant elements that match the specified selector. This is key for sub-selections and nested structures.
  • selection.data([data[, keyFunction]]) − Joins the specified array of data with the selected elements. The optional keyFunction controls how data is matched to elements.
  • selection.join(enter[, update][, exit]) − A powerful method (introduced in D3 v5) to handle the enter, update, and exit selections concisely. enter is a function or selector string for new elements, update for existing, and exit for elements to be removed.
  • selection.enter() − Returns the enter selection: placeholder nodes for data elements that have no corresponding DOM element.
  • selection.exit() − Returns the exit selection: DOM elements that have no corresponding data element.
  • selection.append(type) − Appends a new element of the specified type (e.g., “div”, “svg:circle”) as the last child of each selected element. Often used with the enter selection.
  • selection.remove() − Removes the selected elements from the document. Often used with the exit selection.
  • selection.attr(name, value) − Sets the attribute name to the specified value. If value is a function, it’s evaluated for each element.
  • selection.style(name, value[, priority]) − Sets the style property name to value. If value is a function, it’s evaluated for each element.
  • selection.text(value) − Sets the text content. If value is a function, it’s evaluated for each element.
  • selection.html(value) − Sets the inner HTML. If value is a function, it’s evaluated for each element.
  • selection.each(function) − Invokes the specified function for each selected element, passing (d, i, nodes) where d is the datum, i is the index, and nodes[i] is the current element.
  • selection.call(function[, arguments…]) − Invokes the specified function once, passing the selection itself as the first argument, followed by any optional arguments.
  • selection.filter(filter) − Filters the selection, returning a new selection containing only elements for which the filter (selector string or function) is true.
  • selection.merge(otherSelection) − Merges this selection with another. Useful for combining enter and update selections if not using join().
  • d3.local() − Creates a new local variable scope, allowing you to set and get values on DOM nodes independently of data.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D3.js Selection Example</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
.important { color: red; font-weight: bold; }
</style>
</head>
<body>
<p>This is a normal paragraph.</p>
<p class="info">This paragraph has a class.</p>
<div><p>A nested paragraph.</p></div>
<script>
// Select the body
const body = d3.select("body");
// Select the first paragraph and change its text
d3.select("p").text("This first paragraph was changed by D3!");
// Select all paragraphs and add a class
d3.selectAll("p").classed("important", true);
// Select a specific paragraph by class and change its style
d3.select(".info").style("background-color", "yellow");
// Append a new paragraph
body.append("p").text("This is a newly appended paragraph.");
</script>
</body>
</html>

The Enter-Update-Exit Pattern with selection.join()

Section titled “The Enter-Update-Exit Pattern with selection.join()”

A core D3 pattern is managing elements based on data. selection.join() simplifies this:

const data = [10, 20, 30, 40];
// Select a container and bind data
const circles = d3.select("svg")
.selectAll("circle")
.data(data);
// Use join() to handle enter, update, exit
circles.join(
enter => enter.append("circle") // For new data points, append a circle
.attr("cy", 50)
.attr("r", d => d / 2)
.attr("cx", (d, i) => (i + 1) * 50)
.style("fill", "steelblue"),
update => update.style("fill", "green"), // For existing elements, change fill
exit => exit.remove() // For elements no longer in data, remove them
);

If you only need to handle the enter selection, you can simply pass the enter function or a selector string: selection.join("circle").attr(...) which is shorthand for selection.join(enter => enter.append("circle")).

Selections are used in virtually every D3.js operation:

  • Creating and updating chart elements (bars, circles, lines).
  • Binding data to the DOM.
  • Applying styles and attributes dynamically.
  • Handling user interactions by attaching event listeners to selections.
  • Building complex, data-driven documents.

Understanding selections is crucial for mastering D3. For more examples and detailed explanations, consult the d3-selection documentation and Mike Bostock’s seminal article “How Selections Work”.