Robot Has No Heart

Xavier Shay blogs here

A robot that does not have a heart

Using Size to Debug D3 Selections

Yesterday I was learning about the relatively new General Update Pattern in D3, but I couldn’t get it working. I knew I was missing something obvious, but how to figure out what?

Because I was dealing with nested attributes, I was assigning the selections to variables and then merging them later, so ended up with this heavily simplified (and broken) code to display a list of tiles:

 1 let tiles = container.selectAll('.tile').data(data, d =>
 3 let tilesEnter = tiles.enter()
 4   .append('div')
 5     .attr("class", "tiles")
 8   .attr('color', d => d.color)
10 let contentEnter = tilesEnter
11   .append('span')
12     .attr('class', 'content')
15   html(d => d.content)

When I updated the data, the content of the tile in the child element updated, but the color at the root level did not!

I tried a number of debugging approaches, but the one that I found easiest to wrap my head around, and that eventually led me to a solution, was using the size() to verify how many elements where in each selection.

1 console.log("tiles entering", tilesEnter.size())
2 console.log("tiles updating",'.tile').size())
3 console.log("content entering", contentEnter.size())
4 console.log("content updating",'.content').size())

This allowed me to verify that for the second working case (for data with four elements) that the enter/update selections went from 4 and 0 respectively to 0 and 4 when data was updated. For the first case, the update selection was always zero, and this led me to notice the extra select('.tile') shouldn’t be there for the root case, since we’re already on that selection from the selectAll in the initial setup!

I found logging the entire selection to not be as useful, because it’s confusing what its internal state actually means.

A pretty flower Another pretty flower