score:2

Accepted answer

Generally appending things with a foreach loop isn't the preferable option in d3. This is why you are having difficulty.

The first country in the legend is Albania, and only Albania works in the legend. Why? Because every path in the chart has the same id (the id for Albania):

enter image description here

So, when clicking on Albania in the legend, the on click function searches for the line with id tagAlbania (and looks only for the first entry as IDs should be unique) and toggles it.

The key issue you need to solve is why do all your paths share the same id. Let's look at your code:

  dataNest.forEach(function(d, i) {

    var country = plot.selectAll(".country")
      .data(countries)
      .enter().append("g")       
      .attr("class", "country");

    country.append("path")
      .attr("class", "line")
      .attr("id", 'tag' + d.key.replace(/\s+/g, '')) // assign ID
      .attr("d", function(d) {
        return line(d.values);
      })
      .style("stroke", function(d) {
        return color(d.name);
      });

On the first pass through this for each loop we add a plot for each country using selectAll().data().enter().append(). As we start with an empty selection, .enter().append() will create an element for each item in the data array: all countries' paths are drawn on the first pass.

On the second pass of the loop, the enter selection is empty - there is an element in the initial selection, selectAll('.country'), for each item in the data array. Therefore no elements are entered and appended on each iteration of the loop beyond the first.

Looking back at the first loop, we can see that d is an item in the array dataNest, and on the first loop, d is the zeroth item - Albania. So, as all paths are appended on the first loop, all paths share the same id:

.attr("id", 'tag' + d.key.replace(/\s+/g, '')) // assign ID

To fix that, we could simply change that line to access the datum of the line being appended:

 .attr("id", function(datum) { return 'tag' + datum.name.replace(/\s+/g, '') }) // assign ID

As the datum is the item in the array countries, not dataNest here, I've replaced the property key with the property name

Here's an updated plunkr.


Better yet, we can make this more idiomatic with d3 by dropping the loop altogether, see this plunkr.


Related Query

More Query from same tag