🏠 back to Observable

Label Weirdness

I’ve just started playing with D3 and Observable, and am working on my first chart. I’m creating a timeline that shows the overlaps between various writers’ lifetimes.

I’ve managed to muddle my way through what I considered the hardest bits, but I’ve hit a wall when trying to add labels to the chart; the code I’m using only adds labels to about the bottom 2/3 of the bars.

Here’s the code I’m using:

// add labels
svg.selectAll("text")
  .data(data)
  .enter()
  .append("text")
  .text(function(d) {return d.name})
  .attr("fill", "#ffffff")
  .attr("x", function(d, i) {return x(d.dob) + (dimensions.barPadding * 0.66667)})
  .attr("y", function(d, i) {return ((margin.top * 2.175) + (i * (dimensions.barHeight + dimensions.barPadding)))});

Using the developed console in Firefox, the first <text> element is the one for Bertrand Russell, so it’s not (as far as I can see) a case of the others being positioned incorrectly… they just don’t exist.

Given it’s based on the code I used to create the bars (which works just fine!), I’m not sure what’s going on here, so would really appreciate any pointers.

(Also, if there’s an easier/better way to create data labels, please feel free to call it out.)

1 Like

I sent you a suggestion to merge.

The issue is that when you did the svg.selectAll("text") for your data-join, you were reselecting some of the labels created by the axis component. If you svg.append("g").selectAll("text") instead, you avoid re-selecting those existing elements and instead always create new ones.

I also switched your notebook to use selection.join which makes it easier to implement the general update pattern correctly in D3.

1 Like

Hi, welcome!

An alternate way that I’ve structured labeled graphical elements before is by putting them both inside a group, so something like:

const group = svg.selectAll("g")
  .data(data)
  .join("g")
  ... // shared attributes, if any
const rect = group.append("rect")
  ... // rect-specific attributes
const labels = group.append("text")
  ... // text-specific attributes

The advantage of this kind of organization is that if you want to make your chart dynamic later on, you can add and remove the rects and their text labels at the same time.

Thanks, @mike and @bgchen – I definitely appreciate the help!