I'm working on an Angular component MyGraphComponent
that is supposed to display a graph using D3, where the graph is given by some listOfEdges: Edge[]
and some listOfNodes: Node[]
that are passed to MyGraphComponent
as @Input
s. Every individualNode
in listOfNodes
is supposed to be displayed on the canvas as an Angular component <my-node [node]="individualNode">
that provides functionality for the given node instance. (Imagine e.g. a database schema editor where the nodes are the tables that can be edited.)
Now, I would like to have full control over how and when the nodes are added to the canvas (i.e. the graph's DOM) and, for this reason, I can't just use <my-node *ngFor="let node of listOfNodes">
in my graph component's template. (For instance, I would like to add animations and these animations need to be synchronized with corresponding animations of the edges and other parts of the graph for which D3 is being used.) Put differently, I need to generate all instances of MyNodeComponent
on the fly, so that I can then add them to the DOM (and later remove them, if necessary) using D3.
I have found plenty of sources that explain how to generate Angular components dynamically (see e.g. 1, 2, 3, 4 and, in particular, 5) but at the end they all use Angular's API to add these components to a ViewContainer
. What I would like to do, however, is use D3:
function generateAngularComponent(node: Node): MyNodeComponent {
// Use Angular's component factory to dynamically create
// an instance of MyNodeComponent here and return it. See
// the links for code examples.
}
let nodes: Node[] = [node1, node2, node3, ...];
d3.select(".my-canvas").selectAll(".my-node").data(nodes).enter()
.append(node => {
let component = generateAngularComponent(node);
// Somehow return the DOM of the component here, so that
// D3 adds it to the canvas
});
How do I do this – without breaking my MyNodeComponent
, its change detection, dependency injection and so on? Is this possible at all?