0

All the examples I've seen for representing hierarchical data in d3 involve nesting elements: For example, divs within divs, or table cells within table rows.

What's the "right" way to show hierarchical data where the resulting DOM elements are siblings instead? For example, different levels of headings (h1, h2, etc).

My first attempt (http://jsfiddle.net/herbcaudill/dTd99/) takes this data:

var data = [{
    "key" : "1",
    "values" : [{
            "key" : "101",
            "title" : "Sub Section 1.A"
        }, {
            "key" : "102",
            "title" : "Sub Section 1.B"
        }, {
            "key" : "103",
            "title" : "Sub Section 1.C"
        }
    ],
    "title" : "Section 1"
}, {
    "key" : "2",
    "values" : [{
            "key" : "201",
            "title" : "Sub Section 2.A"
        }, {
            "key" : "202",
            "title" : "Sub Section 2.B"
        }, {
            "key" : "203",
            "title" : "Sub Section 2.C"
        }
    ],
    "title" : "Section 2"
}] 

... and attempts to turn it into headings and subheadings using standard examples that assume we're nesting elements, like this:

d3.select("body").selectAll("h1")
    .data(data)
    .enter()
    .append("h1")
        .text(function(d) {return d.title })
        .selectAll("h2")
            .data(function(d) { return d.values })
            .enter()
            .append("h2")
                .text(function(d) {return d.title})

Of course I end up with nested elements, which is not what I want:

<h1>Section 1
       <h2>Sub Section 1.A</h2>
       <h2>Sub Section 1.B</h2>
       <h2>Sub Section 1.C</h2>
</h1>
<h1>Section 2
       <h2>Sub Section 2.A</h2>
       <h2>Sub Section 2.B</h2>
       <h2>Sub Section 2.C</h2>
</h1>

How can I get this instead?

<h1>Section 1</h1>
<h2>Sub Section 1.A</h2>
<h2>Sub Section 1.B</h2>
<h2>Sub Section 1.C</h2>
<h1>Section 2</h1>
<h2>Sub Section 2.A</h2>
<h2>Sub Section 2.B</h2>
<h2>Sub Section 2.C</h2>
4

1 回答 1

0

OK, I figured this out in the process of posting the question. The solution is to go ahead and do the nesting thing, but attach the data to containing divs; and then add the headings to each div.

var level1 = d3.select("body")
    .selectAll("div.Level1")
    .data(data)
    .enter()
    .append("div").attr("class", "Level1")

level1.append("h1").text(function(d) {return d.title })

var level2 = level1.selectAll("div.Level2")
    .data(function(d) { return d.values })
    .enter()
    .append("div").attr("class", "Level2")

level2.append("h2").text(function(d) {return d.title})

This gives me the following markup:

<div class="Level1">
    <h1>Section 1</h1>
    <div class="Level2">
        <h2>Sub Section 1.A</h2>
    </div>
    <div class="Level2">
        <h2>Sub Section 1.B</h2>
    </div>
    <div class="Level2">
        <h2>Sub Section 1.C</h2>
    </div>
</div>
<div class="Level1">
    <h1>Section 2</h1>
    <div class="Level2">
        <h2>Sub Section 2.A</h2>
    </div>
    <div class="Level2">
        <h2>Sub Section 2.B</h2>
    </div>
    <div class="Level2">
        <h2>Sub Section 2.C</h2>
    </div>
</div>

Working example here: http://jsfiddle.net/herbcaudill/DuJsS/

Update: I agree with @Lars that this is not a great solution. In fact it doesn't really solve the problem that I actually have, which involves adding one table row per node: There's no element that you can nest and use to wrap trs inside a table. So I would welcome a cleaner solution that didn't involve wrapper elements.

于 2013-10-27T18:16:58.430 回答