Stuck with D3.js – using multi-dimensional array to populate select dropdowns

1,397 views
Skip to first unread message

Danny

unread,
Jan 9, 2012, 10:15:44 PM1/9/12
to d3-js
[cross posted from
http://stackoverflow.com/questions/8792586/stuck-with-d3-js-using-multi-dimensional-array-to-populate-select-dropdowns
]

D3.js is simply quite awesome, but I'm stuck on what should be very
simple.

I have two group divs (#RFL & #RFR) containing two divs each (#RFLL,
#RFLR, #RFRL, #RFRR, respectively). I want to put a select dropdown
beneath each 'sub-DIV' – all of which is to be populated by a two
dimensional array.

The trick is, the dropdowns for each 'group' div should be identical.

i.e. in the code below,

RFLL and RFLR should be 1, 2, 3, and RFRL and RFRR should be A, B, C

I've fiddled with this for a long time. I get every combination of
arrangement except the one I want... the version below gives me two
select boxes for each ".RFSubPane" - one too many... I've seen the
section in the documentation as well as http://christopheviau.com/d3_tutorial/

All help / pointers greatly appreciated!


<script>
var l1 = ["1", "2", "3"];
var l2 = ["A", "B", "C"];
var labels = [l1, l2];

function d3test()
{
d3.selectAll(".RFSubPane")
.selectAll(".RFPane")
.data(labels)
.enter()
.append("select")
.selectAll("option")
.data(function (d) {return d;})
.enter()
.append("option")
.text(String);
}
</script>

<div class="RFPane" id="RFL" style="float: left; background: green;">
RFL
<div class="RFSubPane" id="RFLL" style="float: left; background:
blue;"></div>
<div class="RFSubPane" id="RFLR" style="float: right; background:
gray;"></div>
</div>
<div class="RFPane" id="RFR" style="float: right; background: red;">
RFR
<div class="RFSubPane" id="RFRL" style="float: left; background:
blue;"></div>
<div class="RFSubPane" id="RFRR" style="float: right; background:
gray;"></div>
</div>

Mike Bostock

unread,
Jan 9, 2012, 11:13:11 PM1/9/12
to d3...@googlegroups.com
You've almost got it. The weird thing is that your selectors appear to
be inverted: RFSubPane is inside RFPane, so you should select the
panes first. There are two panes, so you can join them to your
two-element labels array:

var pane = d3.selectAll(".RFPane")
.data(labels);

Now, if I understand correctly, you want to add a select element to
each subpane, using the options from the pane's datum. Since you're
using selectAll (there are multiple elements), the subpanes will not
automatically inherit the data from the pane. If you know that there
are always two subpanes per pane, you can duplicate the data:

var subpane = pane.selectAll(".RFSubPane")
.data(function(d) { return [d, d]; });

Now you can create the select element, and by expanding the data
array, the child options:

subpane.append("select").selectAll("option")
.data(function(d) { return d; })
.enter().append("option")
.text(function(d) { return d; ]);

Mike

P.S. If there are a variable number of subpanes, you could use
pane.each to create a context where you can access the parent data,
maybe like this:

pane.each(function(d, i) {
var subpane = d3.select(this).selectAll(".RFSubPane");
});

In this case, you don't actually need to bind data to the subpanes,
and you can say selectAll("option").data(d) rather than using a
function.

Danny

unread,
Jan 10, 2012, 5:14:27 AM1/10/12
to d3-js
Mike,

Thanks! Works like a charm.

Danny
Reply all
Reply to author
Forward
0 new messages