2

I am attempting to load a template dynamically at runtime, render it and bind to dynamic data from within the template.

Following the stackoverflow question How to render a dynamic template with components in Angular2 and @Linksonder's answer I have the loading and rendering part up and running.

Now I am stuck at adding an @Input data to the dynamic component and to provide data so that I can bind to it from the template such as {{ data }}.

I extended the ngOnChanges() in this way so that it adds an injector with a test inputProvider:

createComponentFactory(this.compiler, compMetadata)
  .then(factory => {
    let inputProviders = [{provide: 'data', useValue: '1234'}];  
    let resolvedInputs = ReflectiveInjector.resolve(inputProviders);

    const injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, this.vcRef.parentInjector);

    this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []);
  });

However, trying to access the injector in DynamicComponent this way throws an error (I assume the Injector can not be resolved):

...
import { Injector} from '@angular/core';

export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> {

  const cmpClass = class DynamicComponent {
    data: any;

    constructor(private injector: Injector) {
      this.data = this.injector.get('data');
    }
  };

  const decoratedCmp = Component(metadata)(cmpClass);

  @NgModule({ imports: [CommonModule, RouterModule], declarations: [decoratedCmp] })
  class DynamicHtmlModule { }

  return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule)
   .then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => {
    return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
  });
}

Any help is appreciated. Also if you have other approaches that solve the problem please let me know.

Roman C
  • 49,761
  • 33
  • 66
  • 176
Dan G.
  • 23
  • 3

1 Answers1

0

I suspect this should work for you:

@Injectable()
class DynamicComponent {
  data: any;

  constructor(private injector: Injector) {
    this.data = this.injector.get('data');
  }
}

export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> {
    const decoratedCmp = Component(metadata)(DynamicComponent);

    @NgModule({ imports: [CommonModule, RouterModule, SharedModule], declarations: [decoratedCmp] })
    class DynamicHtmlModule { }

    compiler.clearCacheFor(decoratedCmp);
    return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule)
       .then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => {
        return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
      });
}

Plunker Example

yurzui
  • 205,937
  • 32
  • 433
  • 399