D3 - 未捕获的TypeError:无法读取未定义的属性“长度”

时间:2014-02-13 22:33:44

标签: javascript d3.js

以下代码出错。其余字段的数据没有问题。

<!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

2 个答案:

答案 0 :(得分: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.textd3.csv.parse

答案 1 :(得分:1)

d3.text(filename, callbackFunction)方法(以及所有其他d3文件读取函数)立即返回 ,并在文件具有异步调用指定的回调函数 已成功加载。

必须在回调函数中触发脚本中需要数据运行的所有部分。否则,在数据可用之前,它们将很快执行。这就是为什么在第二行代码执行时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');
});

现在,使用数据集的代码位于回调函数内部,并且保证在数据集准备就绪之前不会执行。或者,您可以将所有代码放在单独的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');
}