0

I am using the exact implementation of angular 2's dynamic component loader as described here: https://angular.io/docs/ts/latest/api/core/DynamicComponentLoader-class.html (specifically the loadAsRoot implementation).

It works fine. However, now I want to extend this in the following way: The parent has certain width x height, which I pass to a service. Then, in the child I subscribe to the service, and render the child dimensions with ngStyle.

This works fine throughout the app, except when I use dynamic component loader! It is not an issue with the service, it fires the width and height to the console correctly upon instantiation of the component. But whatever I put in ngStyle does not get rendered.

What am I doing wrong, and what are my options to work my way around this?

Thank you.

Edit:

Example code:

@Component({
  selector: 'child-component',
  template: '<div [ngStyle]="{'background-color':'red'}">Child</div>'
})
class ChildComponent {
}
@Component({
  selector: 'my-app',
  template: 'Parent (<child id="child"></child>)'
})
class MyApp {
  constructor(dcl: DynamicComponentLoader, injector: Injector) {
    dcl.loadAsRoot(ChildComponent, '#child', injector);
  }
}
bootstrap(MyApp);

The invocation of ngStyle has no effect.

Willem van Gerven
  • 1,407
  • 1
  • 17
  • 24

1 Answers1

1

dcl.loadAsRoot() doesn't configure change detection for the added component, but ngStyle depends on change detection being enabled.

A workaround is explained in https://github.com/angular/angular/issues/6223#issuecomment-195155190

this.appRef._loadComponent(cmpRef);

which uses the private _loadComponent().

DynamicComponentLoader is about to be deprecated anyway and replaced by ViewContainerRef.createComponent().

For a ViewContainerRef.createComponent() example see Angular 2 dynamic tabs with user-click chosen components

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I can't tell from the error message alone. The type argument is because of strict settings for static checks. The type argument isn't technically necessary. – Günter Zöchbauer Jun 03 '16 at 18:33
  • Hi Gunter, I removed my comment because I managed to solve it. For some reason I needed to import ComponentFactory, something that was not needed apparently in your plunker. I wanted to ask you: Your plunker indeed solves my problem. However, perhaps you can advise me in the case where you are getting the types array by service, and that these arrays differ per user. How do I prevent having to import all possible components? Thanks – Willem van Gerven Jun 04 '16 at 08:01
  • 1
    If you use `ComponentFactory` you have to import it. The configuration in Plunker ignores missing types, your local configuration is probably stricter. You do have to import all possible components "somewhere". You can create a class that allows to get the type by name, then you only have to import all components where you set up this class. Where you actually use the map you just import and inject class. – Günter Zöchbauer Jun 04 '16 at 08:14
  • 1
    `class Components { c1:Type = Component1; c2:Type = Component2; }` them inject components and access components as `components.c2`. (I hope the class `Type` is actually a thing for variables that refer to a class.. I don't know TS too well because I use Dart myself.) – Günter Zöchbauer Jun 04 '16 at 08:15