Matt Matt - 1 year ago 222
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() { => {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.


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 Source

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.