关于使用AngularJS和D3的应用程序,我有一个有趣的问题。基本上,我有一个ng-repeat,它根据数组的内容重复。在这个数组中是包含REST URL的对象,它们会定期到达并从中提取数据。获得此数据后,将使用D3绘制图形(阵列中每个对象的一个图形)。
我遇到的问题是通过用户输入动态地将对象添加到此数组,并使绘图正常工作。似乎d3代码跳过枪并开始尝试选择尚未渲染的SVG元素,因为Angular仍在通过ng-repeat完成向DOM添加内容。
我尝试过使用$ timeout,并且还创建了一个类似于此的自定义指令:ng-repeat finish event。
它运行良好,但似乎只是在第一次运行ng-repeat时触发事件,而不是在我向阵列添加另一个对象时。有关处理这种情况的最佳方法的任何评论?如果我可以在每次添加/删除新对象时基于$ last触发事件,然后遍历数组并调用绘图函数,这似乎可以工作。
干杯!
编辑:D3代码目前与此http://bl.ocks.org/mbostock/1346410类似,这只是一个简单的圆环图更新,但需要注意的是重绘是由REST调用触发的。然而,将来可能会有更复杂的图表,这就是我希望使用D3的原因。
编辑2:我已经将我的所有D3代码都移动到了一个自定义指令中,经过大量的乱码后,它几乎可以正常工作。通过不隔离范围,自定义元素具有与ng-repeat相同的范围,并且可以访问对象及其属性,以及相关的DOM元素(当前我正在创建具有每个对象唯一的ID的DIV )。
当使用d3.select时出现问题...当我尝试选择我要放置绘图的DIV时,它不允许我按ID选择,因为它返回null ..这很奇怪关于这个,如果我选择所有(“div”),它可以找到我正在寻找的div,但不会让我选择那个。
这是一个显示我的意思的JsFiddle ...检查控制台并看到第一个测试返回div“obj1”,但第二个选择返回null。
如果我可以让这个工作,然后附加我的SVG画布并在该div中绘图,我认为它会起作用!
相关选择:
var test = d3.selectAll("div");
console.log(test);
var chart = d3.select("#obj" +obj.id);
console.log(chart);
应该创建div的HTML:
<div ng-repeat="object in myData">
<div id="obj{{object.id}}">
Hi
<bars-chart></bars-chart>
</div>
</div>
答案 0 :(得分:3)
根本不需要使用ID进行选择。您只需选择传入Angular指令element[0]
函数的link
:
var chart = d3.select(element[0]).append('svg')
例如:
angular.module('myApp', []).
directive('barsChart', function () {
return {
restrict: 'E',
link: function (scope, element, attrs) {
var chart = d3.select(element[0]).append('svg').attr({height: 20, width: 20});
chart.append('rect').attr({height: 10, width: 10});
}
};
});
function Ctrl($scope, $timeout) {
$scope.myData = [ {"id":"1"}, {"id":"2"}];
// just to show that it reacts to changes in the data and will render more SVGs
$timeout(function() {
$scope.myData.push({"id":"3"});
}, 3000);
}
请参阅JSFiddle: