我必须动态创建树形图(之所以选择D3.js,是因为它可以进行更多的自定义,原因是该图需要大量自定义,但这不是明确的要求。
该图的创建方式类似于可扩展树图的示例(例如https://observablehq.com/@d3/collapsible-tree),不同之处在于我需要将自定义组件作为节点;该组件都需要显示可能的动态数据(尽管可以通过重绘来显示),但最重要的是我需要它来处理事件(单击组件的不同部分)。 使用我的代码(在下面提供),实际上就创建了该组件,并根据我的输入对它的模板进行了评估,但是此后,我找不到将其实际注入到节点中的方法。 在我的代码中,我能够将HTML注入节点中,并且可以在DOM中正确可视化,但是事件处理显然以这种方式丢失(我猜这些操作会丢失Angular位)。 有没有办法实现我的目标?我不知道的API(我尝试过渲染器appendChild,但似乎找不到找到实际父节点的方法),或者用另一种方法将其写出
这是从示例中获得的唯一变化
nodeEnter.append("foreignObject").attr("width", "100").attr("height", "100")
.attr("dy", "0.31em")
.attr("y", d => d._children ? -6 : 6)
.attr("text-anchor", d => d._children ? "end" : "start")
.html((d: d3.HierarchyNode<Graph>) => this.buildComponent(d.data))
.clone(true).lower()
.attr("stroke-linejoin", "round")
.attr("stroke-width", 3)
.attr("stroke", "white");
这是buildComponent方法:
buildComponent(graph: Graph) {
const factory = this.componentFactoryResolver.resolveComponentFactory(PocDataComponent);
const inputs = [
{
'provide': 'entity',
'useValue': graph
}
];
const injector = ReflectiveInjector.fromResolvedProviders(ReflectiveInjector.resolve(inputs), this.injector);
const newLocal = factory.create(injector);
newLocal.instance.entity = graph;
newLocal.changeDetectorRef.detectChanges();
// tslint:disable-next-line: no-string-literal
return newLocal.hostView['rootNodes'][0].innerHTML;
}
图形是一个包含业务信息的简单对象对象
答案 0 :(得分:0)
在这篇文章(https://malcoded.com/posts/angular-dynamic-components/中可以发现,针对此行为,有一个角度不充分的API记录。
基本上,诀窍是使用applicationRef和ViewRef注入来使angular组件代码附加到组件html
基本上,代码可以总结为:
export class ComponentBuilderService {
constructor(private componentFactoryResolver: ComponentFactoryResolver, private injector: Injector, private appRef: ApplicationRef) {}
buildNodeComponent(graph: Graph) {
const factory = this.componentFactoryResolver.resolveComponentFactory(PocDataComponent);
const inputs = [
{
'provide': 'entity',
'useValue': graph
}
];
const injector = ReflectiveInjector.fromResolvedProviders(ReflectiveInjector.resolve(inputs), this.injector);
const newLocal = factory.create(injector);
newLocal.instance.entity = graph;
newLocal.changeDetectorRef.detectChanges();
this.appRef.attachView(newLocal.hostView);
return (newLocal.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
}
一个重要的警告说明(除了声明组件/根据需要添加到EntryComponents之外)可能是在未使用的自举组件(即AppComponent)的构造函数中添加public viewContainerRef:ViewContainerRef。 我无法查明实际原因,但有时,显然取决于我实际在何处运行构建组件(服务或其他组件),如果没有注入,它可能会失败(资源可在本文和在线中找到)