2

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

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

typescripted 组件有一个 ngOnInit 方法,该方法从一个普通的 JS 文件触发一个函数,该文件通过 index.html 中的 script-tag 包含。该函数将 SVG 渲染到上面列出的“div”标签中。SVG 包含一些带有点击指令的 a 元素,这些指令引用了我的组件中的几个方法。

在 SVG 完全编写后调用 $scope.$apply() 之后,这在 Angular1 中运行良好。现在,在 Angular2 中,我的组件中的各个方法都没有被触发。

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

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

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

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

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

PS:

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

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

以及 SVG.js 库生成的标签

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

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

4

3 回答 3

2

我认为 Angular 不会解析您动态添加的 HTML(请参阅Angular2 - 在动态添加的 HTML 中捕获/订阅(点击)事件)。

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

请参阅在 Angular 2 中动态添加事件侦听器

有关更复杂的方法,请参阅Angular 2 中 $compile 的等效项

于 2016-05-27T17:35:18.467 回答
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;

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

于 2016-05-27T14:13:44.780 回答
1

Mark Rajcok 的链接(请参阅“更多涉及的方法”)到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);
 }
于 2016-05-28T08:44:12.560 回答