6

To start with, all the code is available in Plunker.

Some code

I have a root Angular2 component, like this:

import {Component} from '@angular/core'

@Component({
  selector: 'my-app',
  template: `
    <h2>Angular2 Root Component</h2>
    <div data-dynamic-content></div>
  `,
})
export class App {}

The [data-dynamic-content] element is a placeholder for components that I will be adding at runtime. These components are dynamic, too, created like this:

import {Component} from '@angular/core'

export function createComponent(selector: string, value: string) {
  @Component({
    selector: selector, 
    template: `<h4>Dynamic Component: {{v}}</h4>`,
  })
  class MyDynamicComponent {
    v = value;
  }

  return MyDynamicComponent;
};

Please, keep in mind, that this is an extremely simplified example.

Problem statement

I want to create different representations of MyDynamicComponent, append them somewhere into the [data-dynamic-content] element tree, and have them fully-functional.

What I've tried

The only thing that worked so far is bootstrapping the freshly created component upon appending to the DOM:

import {bootstrap} from '@angular/platform-browser-dynamic';
import {createComponent} from './my-dynamic.component';

export function addComponentDynamically(selector, value) {
  var dynamicComponent = createComponent(selector, value);

  var container = document.querySelector('[data-dynamic-content]');
  var wrapper = document.createElement("div");
  wrapper.innerHTML = `<${selector}></${selector}>`;
  container.appendChild(wrapper);

  // !! won't work without this line
  bootstrap(dynamicComponent);
};

I also played with the DynamicComponentLoader. It didn't look like it will fit my needs - the DynamicComponentLoader.loadNextToLocation requires a ViewContainerRef parameter (e.g. you should know beforehand where your component will be located), and I don't have this. As I mentioned before, the MyDynamicComponent could be rendered anywhere in the [data-dynamic-content] element tree, not necessarily in this element itself.

Conclusion

While this works, I seriously doubt that such an approach will be scalable (tested in Chrome with 1000 more complex components - memory consumption peaked at around 750 MB, then reduced to ~ 400 MB).

Is there any better way to make this work than calling bootstrap over and over again?

Dethariel
  • 3,394
  • 4
  • 33
  • 47
  • Dynamically added HTML (like `innerHTML`) is just passed along by Angular and not processed at all. There is no way to make Angular instantiate components or directives or resolve bindings for such HTML. I guess https://github.com/angular/angular/issues/7596 is the closest you can get. – Günter Zöchbauer Jul 29 '16 at 19:43
  • @GünterZöchbauer that's a pretty long thread. Did you try to point to something specific? – Dethariel Jul 29 '16 at 19:46
  • Not really. I don't know what you actually try to accomplish. I think the discussion in the linked issue and the SO link in the issue contain most of the arguments related to your question. – Günter Zöchbauer Jul 31 '16 at 09:38
  • This seems to be what you are looking for: http://stackoverflow.com/questions/38888008/how-can-i-use-create-dynamic-template-to-compile-dynamic-component-with-angular – mcgraphix Jan 27 '17 at 15:29

0 Answers0