Matt Matt - 6 months ago 124
AngularJS Question

Angular2, ZoneJS and externally changed DOM

I need some help concerning an externally changed DOM within an Angular2 RC1 web app. The scenario is simple: I do have a component with an according template that contains an empty div with an ID like this

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


The typescripted component has an ngOnInit method that triggers a function from a plain JS file that is included via script-tag in the index.html. That function renders an SVG into the above listed "div" tag. The SVG contains some a-elements with on-click directives that reference several methods in my component.

That worked fine back then in Angular1 after calling $scope.$apply() after the SVG was completely written. Now, in Angular2 the respective methods in my component are not triggered.

I know, that ZoneJS is now responsible for detecting changes in the DOM. I was hoping that this is done automatically for the whole DOM rendered inside an Angular-managed component. Next try was to inject NgZone in my component and explicitly run the rendering function therein, like this:

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


No success either :-/ Moreover, I registered a MutationObserver (see this thread: Angular2 Directive: How to detect DOM changes), since the problem occurred a little similar to me. It hasn't fired either, though.

I have no clue where to look for, no error message to cling to :-???

Note: It was necessary to use "on-click" instead of "(click)" since the SVG rendering framework refused to set invalid attributes. Obviously attributes starting with a bracket are fine for HTML, but not for XML. However, this should not be the problem, since both directives are perfectly exchangable.

PS:

The rendering method called makes use of the SVG.js framework and looks like this:

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


And the tag generated by the SVG.js lib

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


When I paste the generated SVG code into my template, everything works fine.

Answer

I don't think Angular is going to parse your dynamically added HTML (see Angular2 - catch/subscribe to (click) event in dynamically added HTML).

So, after you call renderSVG(), you'll probably need to traverse the DOM and find the newly added a elements and then manually add (and later remove) an event handler for each one.

See Dynamically add event listener in Angular 2.

For a more involved approach, see Equivalent of $compile in Angular 2.