添加下拉列表会导致未定义的错误

时间:2015-10-14 17:39:55

标签: javascript d3.js

我有一个d3图表,我正在添加节点。这些节点最初有图像和文本。现在我需要添加一个下拉混音。

以下是构建node

的相关代码部分
      var node = svg.selectAll(".node")
        .data(scope.nodes);
      var nodeg = node.enter().append("g")
        .attr("class", "node")
        .call(force.drag);

      nodeg.append("image")
        .attr("xlink:href", function (d) {
          return d.avatar || 'https://github.com/favicon.ico'
        })
        .attr("x", -56)
        .attr("y", -8)
        .attr("width", 64)
        .attr("height", 64);

      nodeg.append("text")
        .attr("dx", 12)
        .attr("dy", ".35em")
        .attr('class', 'name')
        .text(function (d) {
          return d._id === scope.user.profile._id ? 'You' : d.firstName + ' ' + d.lastName
        });

      nodeg.append('select')
        .attr('dx', 12)
        .attr('dy', '1.35em')
        .selectAll('option')
        .data(options)
        .enter()
        .append('option')
        .text(function(o) {
          return o.text;
        })
        .attr('value', function(o) {
          return o.value;
        });

options数组的定义如下:

    var options = [{value: 'M', text: 'Married'},
      {value: 'R', text: 'In a Relationship'},
      {value: 'C', text: 'Child'}];

d3库中发生此错误,因为它正在尝试访问length元素的options属性的select属性:

  

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

... for(R=0,M=N.options.length

我在这里做错了什么?为什么options属性undefined?这在很大程度上模仿了我到目前为止在网上找到的每个例子。

完成示例

var scope = {};

scope.user = {
  profile: {
    _id: 1,
    firstName: 'Billy',
    lastName: 'Bob'
  }
};

scope.nodes = [scope.user.profile];
scope.links = [];

var options = [{
  value: 'M',
  text: 'Married'
}, {
  value: 'R',
  text: 'In a Relationship'
}, {
  value: 'C',
  text: 'Child'
}];

var width = 960,
  height = 500;

var svg = d3.select("body").append("svg")
  .attr("width", width)
  .attr("height", height);

var force = d3.layout.force()
  .nodes(scope.nodes)
  .links(scope.links)
  .charge(-800)
  .linkDistance(200)
  .size([width, height]);

function renderGraph() {
  force.start();

  var link = svg.selectAll(".link")
    .data(scope.links);
  link.enter().append("line")
    .attr("class", "link");

  var node = svg.selectAll(".node")
    .data(scope.nodes);
  var nodeg = node.enter().append("g")
    .attr("class", "node")
    .call(force.drag);

  nodeg.append("image")
    .attr("xlink:href", function(d) {
      return d.avatar || 'https://github.com/favicon.ico'
    })
    .attr("x", -56)
    .attr("y", -8)
    .attr("width", 64)
    .attr("height", 64);

  nodeg.append("text")
    .attr("dx", 12)
    .attr("dy", ".35em")
    .attr('class', 'name')
    .text(function(d) {
      return d._id === scope.user.profile._id ?
        'You' : d.firstName + ' ' + d.lastName
    });

  nodeg.append('select')
    .attr('dx', 12)
    .attr('dy', '1.35em')
    .selectAll('option')
    .data(options)
    .enter()
    .append('option')
    .text(function(o) {
      return o.text;
    })
    .attr('value', function(o) {
      return o.value;
    });

  force.on("tick", function() {
    link.attr("x1", function(d) {
        return d.source.x;
      })
      .attr("y1", function(d) {
        return d.source.y;
      })
      .attr("x2", function(d) {
        return d.target.x;
      })
      .attr("y2", function(d) {
        return d.target.y;
      });

    node.attr("transform", function(d) {
      return "translate(" + d.x + "," + d.y + ")";
    });
  });
}

renderGraph();
.node text {
  pointer-events: none;
}

.node text.name {
  font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

1 个答案:

答案 0 :(得分:0)

感谢Lars,我能够在那里获得select。按预期使用foreignObject就可以了。

      nodeg.append('foreignObject')
        .append('xhtml:select')
        .attr('style', 'margin: 1rem')
        .selectAll('option')
        .data(options)
        .enter()
        .append('option')
        .text(function(o) {
          return o.text;
        })
        .attr('value', function(o) {
          return o.value;
        });