2013-08-02 65 views
5

Tôi đang sử dụng D3 để vẽ bảng HTML và mọi thứ hoạt động tốt khi nhập. Khi tôi thêm một mục mới vào bộ sưu tập dữ liệu của tôi, nó sẽ thêm mục mới vào bảng một cách chính xác.Vẽ bảng HTML qua D3 không cập nhật dữ liệu hiện có

Vấn đề là bất cứ khi nào tôi cập nhật một đối tượng hiện có (một đối tượng trong bộ sưu tập backgroundJobs bên dưới) trong bộ sưu tập. Khi tôi chạy lại mã D3 để đồng bộ hóa bảng, nó không hoạt động. Chẳng có gì xảy ra.

Dưới đây là các mã:

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

Trả lời

7

Vui lòng tham khảo phần giải thích thú vị của data joins.

Khi bạn gọi

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

Bạn thực sự có được 3 lựa chọn: 'nhập' (hộ các yếu tố mới không có mặt trong DOM chưa), 'thoát' (những người có mặt trong DOM nhưng không còn hiện diện trong dữ liệu) và 'cập nhật' có chứa các nút đã có trong DOM và vẫn có dữ liệu được gán cho chúng thông qua cuộc gọi .data ở trên. Nói chung, để lựa chọn 'enter' bạn tạo nút mới, để 'thoát' bạn cần phải loại bỏ các nút cũ, và để 'cập nhật' bạn chỉ cần thay đổi thuộc tính - có thể có hiệu ứng chuyển tiếp đẹp mắt. Xem mã chức năng 'đánh dấu' được cập nhật.

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

Xem Demo (backgroundJobs được bật hẹn giờ giữa hai tập dữ liệu mã hóa cứng).

+1

tại sao bao gồm các cuộc gọi 'rows.order();'? – manu08

+0

Vì vậy, thứ tự các hàng trong bảng khớp với thứ tự công việc trong mảng backgroundJobs. Nếu không phân loại rõ ràng tất cả các công việc mới ('mới' về tham gia dữ liệu - những thứ tạo thành lựa chọn 'nhập') được nối vào cuối bảng. – amakhrov

1

Biến rows sẽ là một lựa chọn mà sẽ chỉ chứa nút nếu enter() là không có sản phẩm nào. Lần thứ hai xung quanh, nếu bạn chưa thêm bất kỳ hàng mới nào vào backgroundJobs, liên kết dữ liệu sẽ cập nhật các nút hiện có và enter() sẽ không chứa bất kỳ nút nào (nghĩa là rows sẽ không chứa bất kỳ nút nào).

Bạn có thể làm được việc này bằng cách giữ một tham chiếu đến các lựa chọn cập nhật lợi dụng thực tế là node nối vào lựa chọn nhập được thêm vào sự lựa chọn cập nhật đằng sau hậu trường:

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

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

Bây giờ hàng sẽ giới thiệu vào một lựa chọn có chứa tất cả các nút hiện có và mới được thêm trước đó.

0

Để có thể thêm và xóa hàng tự động, chiến lược này làm việc cho tôi:

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