Angular2,ZoneJS和外部更改的DOM

时间:2016-05-27 14:11:53

标签: angularjs dom angular zonejs

我需要一些关于Angular2 RC1网络应用程序中外部更改的DOM的帮助。场景很简单:我确实有一个带有相应模板的组件,其中包含一个带有这样的ID的空div

<div id="my-svg-canvas"></div>

typescripted组件有一个ngOnInit方法,它从一个普通的JS文件中触发一个函数,该文件通过index.html中的script-tag包含在内。该函数将SVG呈现为上面列出的“div”标记。 SVG包含一些带有on-click指令的a元素,这些指令引用了我的组件中的几个方法。

在调用$ scope后,在Angular1中工作正常。在完全写入SVG后,$ apply()。现在,在Angular2中,我的组件中的各个方法不会被触发。

我知道,ZoneJS现在负责检测DOM中的变化。我希望这是在Angular管理的组件内呈现的整个DOM自动完成的。接下来尝试在我的组件中注入NgZone并在其中显式运行渲染函数,如下所示:

ngOnInit() {
  this.ngZone.run(() => {renderSVG(this.myData, "my-svg-canvas");})
}

也没有成功: - /此外,我注册了一个MutationObserver(请参阅此主题:Angular2 Directive: How to detect DOM changes),因为问题发生的情况与我有点类似。但它也没有解雇。

我不知道在哪里寻找,没有错误信息要坚持: - ???

注意:由于SVG渲染框架拒绝设置无效属性,因此必须使用“on-click”而不是“(click)”。显然,以括号开头的属性适用于HTML,但不适用于XML。但是,这不应该是问题,因为这两个指令都是完全可以交换的。

PS:

调用的呈现方法使用SVG.js框架,如下所示:

function renderSVG(dataParam, elementIdParam) {
  draw = SVG(elementIdParam).spof();
  initAndPaint(draw, dataParam);
  return draw; 
 }

由SVG.js lib生成的标签

<a id="SvgjsA1033" on-click="showVal('W1')" class="union">

当我将生成的SVG代码粘贴到我的模板中时,一切正常。

3 个答案:

答案 0 :(得分:2)

我不认为Angular会解析动态添加的HTML(请参阅Angular2 - catch/subscribe to (click) event in dynamically added HTML)。

因此,在您调用renderSVG()之后,您可能需要遍历DOM并找到新添加的a元素,然后为每个元素手动添加(以后删除)事件处理程序之一。

请参阅Dynamically add event listener in Angular 2

有关更具参与性的方法,请参阅Equivalent of $compile in Angular 2

答案 1 :(得分:1)

我会将您的代码移动到组件的ngAfterViewInit挂钩方法中:

ngAfterViewInit() {
  this.ngZone.run(() => {renderSVG(this.myData, "my-svg-canvas");})
}

此外,您应该使用ViewChild装饰器引用您的DOM元素:

<div #mySvgCanvas"></div>

@ViewChild('mySvgCanvas')
mySvgCanvasElt: ElementRef;

ngAfterViewInit() {
  var elt = this.mySvgCanvasElt.nativeElement;

我认为这里不需要明确使用区域......

答案 2 :(得分:1)

Mark Rajcok的链接(参见&#34;对于更复杂的方法&#34;)在接受的答案中使用DynamicLoaderComponent的解决方案。作为这个线程的闭包,这是我的实现:

constructor(private loader: DynamicComponentLoader, private injector:Injector) {}

ngAfterViewInit() {
  let tournamentCanvas = document.createElement("canvas");
  renderKOTournamentSVG(this.tournament, tournamentCanvas);

  @Component({
    selector: 'canvas-component',
    template: tournamentCanvas.outerHTML)}
  class CanvasComponent {}

  this.loader.loadAsRoot(CanvasComponent, "canvas-component", this.injector);
 }