I want to draw multiple svg lines (using D3.js) from a nested object structure like this:
data = [
{ Name: "jim", color: "blue", Points: [{x:0, y:5 }, {x:25, y:7 }, {x:50, y:13}] },
{ Name: "bob", color: "green", Points: [{x:0, y:10}, {x:25, y:30}, {x:50, y:60}] }
];
var line_gen = d3.svg.line().interpolate("linear")
.x(function(d){return d.x;})
.y(function(d){return d.y;});
My first attempt, based on this question was to use svg:g to represent the first nesting level, then access the second nesting level within the group to render the lines:
var g = svg.selectAll(".linegroup")
.data(data).enter()
.append("g")
.attr("class", "linegroup")
.style("stroke", function(d) { return d.color; })
.style("fill", "none");
g.selectAll(".line")
.data(function(d) { return d.Points;})
.enter().append("svg:path")
.attr("d", line_gen);
But this did not render any lines. Instead, inside each group I got an empty path tag for each of the three data points. So apparently the shape of the data is causing problems.
<g class="linegroup" style="stroke: #0000ff; fill: none;">
<path></path>
<path></path>
<path></path>
</g>
I did find one solution (will post as answer) that doesn’t use groups, but I would still like to know why the group solution doesn’t work.
Here is an answer, largely based on this question except that it doesn’t use d3.entries:
The key approach here is to not return the line_gen function directly to the “d” attribute but to wrap it in another function that passes the correct nested array from the outer object.
See also this great discussion on d3.entries vs. d3.values. d3.entries seems to be suggested a lot for similar problems but I don’t think it really helps in my case.