Appending multiple non-nested elements for each data member with D3.js
I would like to create multiple non-nested elements using d3 to create a structure like this:
<div id="parent">
<p> from data[0] </p>
<p> from data[0] </p>
<p> from data[1] </p>
<p> from data[1] </p>
<p> from data[2] </p>
<p> from data[2] </p>
</div>
creating nested structures would go something like
d3.select('#parent').selectAll('p').data(data).enter().
append('p')...append('p')
but I would like to maintain the original selection even after the append, so I could continue appending to the parent element. Thank you!
Solution 1:
The idomatic way of doing is with nesting:
var divs = d3.select('#parent').selectAll('p').data(data).enter().append('div');
divs.append('p')
divs.append('p')
Which creates:
<div id="parent">
<div>
<p> from data[0] </p>
<p> from data[0] </p>
</div>
<div>
<p> from data[1] </p>
<p> from data[1] </p>
</div>
<div>
<p> from data[2] </p>
<p> from data[2] </p>
</div>
</div>
If that won't work, save your selection and repeatedly append:
var enterSelection = d3.select('#parent').selectAll('p').data(data).enter();
enterSelection.append('p')
enterSelection.append('p')
then sort what you've added:
d3.select('#parent').selectAll('p').sort(function(a, b){ return a.index - b.index; })
You'll need to add an index
property to each element of data
that describes the sort order. The normal i
is only defined in the context of a particular selection, which is lost when we reselect.
Solution 2:
Use append()
for the first item and insert()
for the second. This eliminates any need to sort afterwards (thanks to @scuerda's comment for pointing this out) (JSFiddle):
data = [{}, {}, {}];
var enterSelection = d3.select('#parent').selectAll('p').data(data).enter()
enterSelection.append('p').text(function(d, i) {return 'from data[' + i + ']'})
enterSelection.insert('p').text(function(d, i) {return 'from data[' + i + ']'})
This will give you the exact structure requested:
<p>from data[0]</p>
<p>from data[0]</p>
<p>from data[1]</p>
<p>from data[1]</p>
<p>from data[2]</p>
<p>from data[2]</p>