I have been pondering pretty much the same problem for a while and come to the following conclusion.
The simplest way to integrate Angular created elements with d3 is to add the directives with .attr
and then .call
the compile service on the d3 generated elements. Like this:
mySvg.selectAll("circle")
.data(scope.nodes)
.enter()
.append("circle")
.attr("tooltip-append-to-body", true)
.attr("tooltip", function(d){
return d.name;
})
.call(function(){
$compile(this[0].parentNode)(scope);
});
I think the idea of generating elements with Angular ngRepeat
rather than d3 is working against the frameworks. D3 does not expect to be handed a bunch of elements. It wants to be handed data - almost always an array. It then has a stack of excellent functions to convert that data into various SVG or HTML elements. Let it do that.
It seems from this quote...
D3 makes it trivial to add elements and bind each to the data it represents, but the graph visualization is only part of a much larger application: I need to create different types of elements representing these same nodes and edges in different parts of the application (which D3 has nothing to do with), and I'd like to keep all of these elements bound to a single dataset.
... you are implying that generating elements with d3 somehow prevents you from binding the same data to different parts of the application. I can't see why. Just have d3 generate elements from a scope array (as is done in the linked Plunker). Then use the same dataset wherever you want in the usual Angular way. Other parts of the application can update the dataset and a $watch
callback can re-render the d3 graphic.