2014-02-13 2 views
1

Ошибка в коде ниже. Нет никаких проблем с данными остальных полей.D3 - Uncaught TypeError: Не удается прочитать свойство 'length' undefined

<!DOCTYPE html> 
<html> 
<head> 
<title>Data Entry</title> 
<meta charset='utf-8'/> 
<meta name="keywords" content="D3"/> 
<script type="text/javascript" src="d3/d3.v3.js"></script> 
<style type="text/css"> 
.table {border: 2px; text-align: center;} 
.th {font-size: 12px; font-weight: bold; color: blue;} 
.td {font-size: 12px;} 
</style> 
</head> 
<body> 
<script type="text/javascript"> 
var dataset; 
d3.text('data.txt', function(d){dataset = d3.csv.parse(d, function(d){return {id: +d.id, name: d.name};});}); 
d3.select('body').append('table').attr('class','table').selectAll('tr').data(dataset).enter().append('tr'); 
</script> 
</body> 
</html> 

Скриншот ниже: Error in Chrome

+0

Ошибка в строке d3.select, и я подозреваю из-за данных (набора данных). – codepk

ответ

2

Есть две вещи, которые необходимо учитывать, во-первых, что вы разместили ссылку к набору данных за пределами функции обратного вызова. Поэтому, пока вы создали переменную dataset как глобальную, чтобы ее можно было получить за пределами блока d3.text, у нее не было времени для заполнения при создании таблицы. Поэтому, если вы переместите код генерации таблиц в блок d3.text, вы рассмотрите эту проблему. Вы также можете поставить очередь запросов данных, используя queue.js.

Другое дело в том, что вы пытались связать один элемент массива объектов, где вам нужен массив объектов, так как d3 итерации над массивом создают в этом случае строки таблицы. Затем информация в объектах используется для заполнения вашей таблицы.

Оба эти вопроса рассматриваются в следующем коде, однако, обратите внимание, что я не заполнял ячейки ячеек какой-либо вещью, просто создал строки. Для этого я предлагаю прочитать d3noobs post и ответ со ссылкой на stackoverflow на Shawn Allen.

var dataset =[]; 
d3.text('data.txt', function(d) { 
    d3.csv.parse(d, function(d) { 
     var el = { 
      id: +d.id, 
      name: d.name 
     }; 
     dataset.push(el) 
    }); 
var table = d3.select('body') 
    .append('table') 
    .attr('class', 'table'); 

table.selectAll('tr') 
    .data(dataset).enter() 
    .append('tr') 
    .attr("class", "rows"); 

}); 

Одно последнее дело в том, что вы могли бы просто использовать d3.csv вместо d3.text и d3.csv.parse.

+0

Отлично! Спасибо за ссылки. – codepk

1

d3.text(filename, callbackFunction) метод (и все другие d3 функции чтения файла) возвращают сразу и вызвать указанную функцию обратного вызова асинхронно, когда файл был успешно загружен.

Все части вашего скрипта, которые требуют функции для работы, должны запускаться из функции обратного вызова. В противном случае они будут выполняться слишком быстро, прежде чем данные будут доступны. Вот почему dataset был не определен, когда вторая строка кода выполнена, хотя она была там, когда вы обращались к ней с консоли.

Try:

d3.text('data.txt', function(d){ 
    dataset = d3.csv.parse(d, function(d){ 
        return {id: +d.id, name: d.name}; 
       }); 
    d3.select('body').append('table') 
      .attr('class','table') 
     .selectAll('tr') 
     .data(dataset) 
     .enter() 
      .append('tr'); 
}); 

Теперь код, который использует набор данных находится внутри функции обратного вызова, и гарантированно не выполнять, пока набор данных не будет готов. С другой стороны, вы могли бы поместить весь код в отдельном initialize() функции и вызвать эту функцию внутри вашей функции синтаксического анализа данных:

d3.text('data.txt', function(d){ 
    dataset = d3.csv.parse(d, function(d){ 
        return {id: +d.id, name: d.name}; 
       }); 
    initialize(); 
}); 

function initialize() { 
    d3.select('body').append('table') 
      .attr('class','table') 
     .selectAll('tr') 
     .data(dataset) 
     .enter() 
      .append('tr'); 
} 
+2

Рабочий пример: http://plnkr.co/edit/s4d3YxI9uDOi7UD5G6cN?p=preview :) –

Смежные вопросы