最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

d3.js - In d3 for javascript, how do you create different elements for your data? - Stack Overflow

matteradmin4PV0评论

For example, in a html <table>, a <tr> may contain <th> and <td>. How would you bind data to a row selection that would create even columns as <th> and odd as <td>?

For example, in a html <table>, a <tr> may contain <th> and <td>. How would you bind data to a row selection that would create even columns as <th> and odd as <td>?

Share Improve this question edited Dec 24, 2015 at 21:28 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Aug 27, 2012 at 14:33 Mats JohnsonMats Johnson 633 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 3

So, this doesn't seem perfect either, but there's always the html() method.

​var d = [['a','b','c','d']];

var r = d3.select('#myTable').selectAll('tr')
    .data(d);

r.enter().append('tr').html(function(d) {
    var i, s = '';
    for (i = 0; i < d.length; i += 1) {
        s += (i%2===0) ? '<th>' : '<td>';
        s += d[i];
        s += (i%2===0) ? '</th>' : '</td>';
    }
    return s;
}​​​​​​​​​​​​​​​);

As far as I can tell, you're correct - there's no way to do this within the standard D3 idiom. Presumably this will be possible once selection.append() can take a function:

selection.append(name)

Appends a new element with the specified name... The name must be specified as a constant, though in the future we might allow appending of existing elements or a function to generate the name dynamically.

Hopefully such a function would take the standard (data, index) arguments, and would solve this problem. Otherwise, at the moment, there's no way I can see to create different elements off of a single .enter() selection - .enter() only supports .append, .insert, and .select, none of which can take a function argument.

You can get some of what you want by munging the data into tuples and double-appending to the .enter() selection, as shown here: http://jsfiddle/xuJ6w/4/

// munge data
var tuples = data.map(function(row) {
    var newRow = [],
        x;
    // create array of objects
    for (x=0; x<row.length; x+=2) {
        newRow.push({
            label: row[x],
            value: row[x+1]               
        })
    }
    return newRow;
});

var rows = d3.select('table').selectAll('tr')
    .data(tuples);

rows.enter().append('tr');
    
var cellPairs = rows.selectAll('.cell')
    .data(function(d) { return d; });
    
var entry = cellPairs.enter();
entry.append('th')
    .attr('class', 'cell')
    .text(function(d) {
        return d.label;
    });
entry.insert('td', 'th + th')
    .attr('class', 'cell')
    .text(function(d) {
        return d.value;
    });

But as you can see, when the update is called:

cellPairs
    .style('background', '#CCC');

Only the last-appended nodes are updated, so the data hasn't been fully bound.

The best I can e up with is making a <td> look like a <th> by applying a class based on the index of the data:

var d = ['a','b','c','d','e','f','g'];

var tr = d3.select("#myTableRow").selectAll("td")
    .data(d).enter().append("td")
    .text(function(d) { return d; })
    .classed("thLike", function(d,i) { return i%2===0; });

CSS:

.thLike {
    font-weight: bold;
}

https://github./mbostock/d3/wiki/Selections#wiki-data

Selectors can also be intersected (".this.that" for logical AND) or unioned (".this, .that" for logical OR).

So, something like this might work for you. I haven't tested though (if this selection doesn't work, you can just add the same class to each of the TD/TH cells and select that with TR .myClass):

var cells = tableRow.selectAll("TD, TH").data(data);
cells.enter().each(d, i) {
    var cell = d3.select(this);
    cell.append(i%2 ? "TD" : "TH");
})
Post a comment

comment list (0)

  1. No comments so far