1

This is actually a spin off from here, with a much simpler use case, though. It is about how to let Angular2 know that there are externally added DOM elements containing Angular directives. In this case, I add a new click button whose on-click event is never bound. Imo I thought Zone would automatically detect any changes in the templates of their components, obviously it doesn't. Is anyone able to make that code work without the immense overhead of creating a new component for the button and load it via DynamicLoaderComponent ?

Note: I've already added NgZone and ChangeDetectorRef to play around with. Neither worked for me.

Here is a link to the full example at plunkr: plnkr.co/edit/hf180P6nkxXtJDusPdLb

And this is an relevant excerpt from the component:

import {Component, AfterViewInit, ChangeDetectorRef, NgZone, Renderer} from '@angular/core'

@Component({
    selector: 'my-app',
providers: [],
template: `
<div>
<p><button on-click="clickMe()">This works</button></p>

<div id="insert-here"></div>

</div>
`,
directives: []
})
export class App implements AfterViewInit {
constructor(private ref:ChangeDetectorRef, private ngZone:NgZone, private renderer:Renderer) {

}

clickMe() {
alert("Yay, it works");
}

ngAfterViewInit() {
    let newButton = document.createElement("button");
    newButton.setAttribute("on-click","clickMe()");
    let textNode = document.createTextNode("This does not");
    newButton.appendChild(textNode);
    document.getElementById("insert-here").appendChild(newButton);

    // please make my button work:
    this.ref.detectChanges();
}

}
Community
  • 1
  • 1
Jan B.
  • 6,030
  • 5
  • 32
  • 53
  • If all you require is adding an event, you can do `newButton.addEventListener('click',this.clickMe);` without needing `NgZone` or `ChangeDetectorRef` – Abdulrahman Alsoghayer May 29 '16 at 09:11
  • Thanks, Abdulrahman. Unfortunately there is more than that. I've got dozens of large SVG with up to 50 different click events within a SVG. I really need Angular to do the job. Actually it is something that is inherent to the very core of it: scanning markup and binding logic to directives. – Jan B. May 29 '16 at 09:27

1 Answers1

1

Zone doesn't care about the DOM at all. Zone only patches async APIs like addEventListener(), setTimeout(), ... and then checks only the model for changes.

Angular assumes that it is in charge of the DOM. The DOM is updated by Angular when the model changed, not the other way around.

There is no way to make Angular create components or directives for matching HTML or resolve bindings for HTML added dynamically. Angular does this only for HTML added statically to the template of a component.

DynamicaComponentLoader (deprecated) or ViewContainerRef.createComponent() are the way to go for adding components dynamically.

You can use wrapper element that makes it easy to declaratively add dynamic components like explained in Angular 2 dynamic tabs with user-click chosen components (also contains a Plunker example for the new ViewContainerRef.createComponent()

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thanks for the explanation and a suggestion how to solve this issue! On the other hand, every template needs to be scanned initially, so it should be possible to rescan it and detect unbound directives. I assume this feature is required for a lot of migrations to Angular2 and could be handled with a one-liner like $scope.$apply in v1. I guess it's worth submitting a feature request. – Jan B. Jun 02 '16 at 12:49
  • Angular only scans the template. This is before it is added to the DOM. Angular doesn't scan the DOM at all. There was a feature request very recently to apply `_ng_content_xxx` classes for dynamically added HTML because CSS scoping is not applied for such HTML. This was also rejected by Misko. Therefore I think it's quite unlikely for such a change to happen. – Günter Zöchbauer Jun 02 '16 at 12:55
  • 1
    Ok, I see. I don't intend to clutter up their ticket system. It's pretty filled up, anyway. Thanks for you rapid responses in all Angular related questions here on stackoverflow, by the way. – Jan B. Jun 02 '16 at 13:16
  • Thanks for the feedback :) – Günter Zöchbauer Jun 02 '16 at 13:17
  • Just stumbled again over the issue I mentioned above in case you are interested https://github.com/angular/angular/issues/8936#issuecomment-223257597 – Günter Zöchbauer Jun 02 '16 at 13:20