我正在使用D3绘制HTML表格,并且在输入时效果很好。当我向数据集合添加新项目时,它会正确地将新项目添加到表中。
问题是每当我更新集合中的现有对象(下面的backgroundJobs集合中的对象)时。当我重新运行D3代码以同步表时,它不起作用。没有任何事情发生。
以下是代码:
var visibleColumns = ['Name', 'Start', 'End', 'Status', 'Metadata', 'Errors'];
var table = d3.select('#jobs').append('table');
var thead = table.append('thead');
var tbody = table.append('tbody');
thead.append("tr")
.selectAll("th")
.data(visibleColumns)
.enter()
.append("th")
.text(function (column) { return column; });
function tick() {
var rows = tbody.selectAll("tr")
.data(backgroundJobs, function(d) {
return d.name;
})
.enter()
.append("tr");
var cells = rows.selectAll("td")
.data(function(row) {
return [{column: 'Name', value: row.name},
{column: 'Start', value: row.startedTimestamp},
{column: 'End', value: row.endedTimestamp},
{column: 'Status', value: row.isRunning},
{column: 'Metadata', value: ''},
{column: 'Errors', value: row.errorMsg}];
})
.enter()
.append("td")
.text(function(d) { return d.value; });
}
setInterval(tick, 500);
答案 0 :(得分:9)
请参阅data joins的精彩解释。
致电时
tbody.selectAll("tr").data(some-new-data);
你实际上有3个选择:'enter'(尚未在DOM中出现新元素),'exit'(存在于DOM中但不再存在于数据中的那些元素)和'update'包含的节点是已经在DOM中,并且仍然通过上面的.data调用将数据分配给它们。
一般来说,对于'enter'选择你创建新节点,'exit'你需要删除旧节点,而'update'你只需要改变属性 - 可能会有一些很好的过渡效果。 请参阅更新的“tick”功能代码。
function tick() {
var rows = tbody.selectAll("tr")
.data(backgroundJobs, function(d) {
return d.name;
});
rows.enter()
.append("tr");
rows.order();
var cells = rows.selectAll("td")
.data(function(row) {
return [{column: 'Name', value: row.name},
{column: 'Start', value: row.startedTimestamp},
{column: 'End', value: row.endedTimestamp},
{column: 'Status', value: row.isRunning},
{column: 'Metadata', value: ''},
{column: 'Errors', value: row.errorMsg}];
});
cells.enter()
.append("td");
cells.text(function(d) { return d.value;});
cells.exit().remove();
rows.exit().remove();
}
请参阅Demo(backgroundJobs在两个硬编码数据集之间启用了计时器。)
答案 1 :(得分:1)
如果rows
不为空,enter()
变量将只包含节点。第二次,如果你没有在backgroundJobs
中添加任何新行,数据绑定将更新现有节点,enter()
将不包含任何节点(意味着rows
won' t包含任何节点。)
您可以通过保留对更新选择的引用来解决这个问题,利用输入选择中添加的节点添加到幕后更新选择的事实:
var rows = tbody.selectAll("tr")
.data(backgroundJobs, function(d) {
return d.name;
});
rows.enter()
.append("tr");
现在,行将引用包含所有先前存在和新添加的节点的选择。
答案 2 :(得分:0)
为了能够动态添加和删除行,此策略适用于我:
// ROW MANAGEMENT
// select all tr elements
var tr = this.table.select("tbody").selectAll("tr").data(cur_data);
// exit rows
tr.exit().remove();
// enter rows
var trEnter = tr.enter().append("tr");
// CELL MANAGEMENT
trEnter.selectAll("td").data(function(d) { return d3.values(d); }).enter().append("td").text(function(d) { return d; });
// select all td elements
var td = tr.selectAll("td").data(function(d) { return d3.values(d); });
// exit cells
td.exit().remove();
// enter and update/add data to cells
td.enter().append("td");
td.text(function(d) { return d; });