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

For example, in a html <table>, a <tr> may contain <th> and <td>. How would you

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");
})

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745654153a4638442.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信