2013-08-02 8 views
5

D3を使用してHTMLテーブルを作成しています。データコレクションに新しいアイテムを追加すると、新しいアイテムがテーブルに正しく追加されます。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); 

答えて

7

data joinsのクールな説明を参照してください。

あなたはあなたが実際に3つの選択を取得

tbody.selectAll("tr").data(some-new-data); 

を呼び出します(まだDOMに存在しない新しい要素whith)「を入力」、「終了」(に存在するDOMに存在しなくなりましたものをデータ)と、既にDOM内にあり、上記の.data呼び出しを介してそれらに割り当てられたデータを持っているノードを含む '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(); 
} 

(backgroundJobsは、2つのハードコーディングされたデータセット間タイマーに切り替えられた)Demoを参照してください。

+1

なぜ「)(rows.order;」コールが含まれていますか? – manu08

+0

テーブル行の順序がbackgroundJobs配列のジョブの順序と一致するようにします。 明示的にソートすることなく、テーブルの最後にすべての新しいジョブ(データ結合に関して「新規」 - 「入力」選択を形成するもの)が追加されます。 – amakhrov

1

rows変数がenter()が空でない場合にのみ、ノードが含まれています選択になります。ここでは

コードです。 2回目に、新しい行をbackgroundJobsに追加しないと、データバインドによって既存のノードが更新され、enter()にはノードが含まれません(つまり、rowsにはノードが含まれません)。あなたが入力した選択に追加するノードという事実を利用して、更新の選択への参照を保持することにより、これを回避することができます

は舞台裏で、更新の選択に追加されます:

var rows = tbody.selectAll("tr") 
    .data(backgroundJobs, function(d) { 
     return d.name; 
    }); 

rows.enter() 
    .append("tr"); 

今の行が参照されます以前に存在していたノードと新しく追加されたノードがすべて含まれている選択に移動します。

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; }); 
関連する問題