我正在将带有图表的基于 D3 的网站迁移到 Angular。每个单独的图表仍将由 D3 绘制,但每个图表都将使用管理图表的 Angular 指令
。
其中一个图表元素由图表 (SVG) 和充当其图例的 HTML 表格组成。
[ svg (chart) ][ table (legend) ]
D3 绘制图表,我使用 ng-repeat 绘制图例。在这种情况下,图例和图表都需要是交互式的:需要有 DOM 事件监听器。然而,指令的 Controller 在 ng-repeat 绘制图例之前运行(因此 DOM 元素尚不存在)。
查看:
<div ng-transclude></div>
<div class="wrapper">
<svg></svg>
<div class="valign">
<table>
<tr>
<th>#</th>
<th>Name</th>
<th>BTC</th>
<th>USD</th>
</tr>
<tr ng-repeat="item in items" class="legend item-{{item.title}}" title="{{item.title}}">
<th>{{$index + 1}}</th>
<td>{{item.title}}</td>
<td>{{item.btc | bitcoin}}</td>
<td>{{item.usd | currency}}</td>
</tr>
</table>
</div>
</div>
指令:
angular
.module('d3.charts', [])
.directive('volumeElement', function() {
return {
restrict: 'E',
scope: {
data: '='
},
transclude: true,
link: function(scope, element, attrs) {
// todo: this needs to be changed upstream in the volume controller
scope.mode = '24h';
// the d3 chart function
var chart = new window.WZB.VolumeChart(
element.find('svg')[0],
scope.data
);
var $paths, $legend;
var render = function() {
chart.mode = scope.mode;
chart.render();
$paths = element.find('.interactive');
addHovers();
}
var addHovers = function() {
// PROBLEM: at this point the ng-repeat has not populated the legend yet
$legend = element.find('.legend')
$paths.hover(function(e) {
var $path = $(e.target);
var title = $path.attr('title');
var legend = $legend
.filter(function() {
var nonActive = $(this).attr('title') !== title;
if(!nonActive)
$(this).removeClass('blur')
return nonActive;
})
$paths
.not($path)
.add(legend)
.addClass('blur');
}, function() {
$paths.add($legend)
.removeClass('blur');
})
}
render();
},
templateUrl: '/volume-element.html'
}
})
我使用 jQuery 进行更高级的 DOM 操作,我不能只依赖 Angular 的 ng-mouseover 指令,因为我需要 Angular 生成的表和 D3 生成的 SVG 的事件监听器。
如何在 ng-repeat
填充图例后立即执行代码?
黑客解决方案:
// todo: proper fix
// see @link https://stackoverflow.com/questions/24035289/angularjs-add-jquery-dom-eventlisteners-after-ng-repeat
setTimeout(addHovers, 0);
最佳答案
我重构了代码,我没有以 Angular 方式思考。包含新指令,并且 d3 还创建表格,而不是混合 Angular 和 d3 来实现相同的可视化。这样我就不再需要 jQuery 了。
关于javascript - AngularJS 在 ng-repeat 之后添加 jQuery dom 事件监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24035289/