How do you use @Input with components created with a ComponentFactoryResolver?

Angular

Angular Problem Overview


Is there a method that can be used to define an @Input property on an Angular 2 component that's created dynamically?

I'm using the ComponentFactoryResolver to create components in a container component. For example:

let componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentName);

let componentRef = entryPoint.createComponent(componentFactory);

Where "entryPoint" is something like this in the component HTML:

<div #entryPoint></div>

And defined in my container component with:

@ViewChild('entryPoint', { read: ViewContainerRef } entryPoint: ViewContainerRef;

This works well, but I can't find a way to make an @Input property work on the newly created component. I know that you can explicitly set public properties on the component class, but this doesn't seem to work with ng-reflect. Prior to making this change I had a "selected" property decorated with "@Input()" that caused Angular to add the following to the DOM:

<my-component ng-reflected-selected="true"></my-component>

With this in place I was able to dynamically update the markup to switch a CSS class:

<div class="header" [class.active-header]="selected === true"></div>

Based on some searching I was able to find a method to make "@Output" work as expected, but I've yet to find anything for @Input.

Let me know if additional context would be helpful and I'd be happy to add it.

Angular Solutions


Solution 1 - Angular

No, Angular2 bindings only work with components and directives statically added to the template of a component.

For all other situations use shared services like explained in https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service

You can also use

let componentRef = entryPoint.createComponent(componentFactory);
componentRef.instance.someProp = 'someValue';
componentRef.instance.someObservableOrEventEmitter.subscribe(data => this.prop = data);

Solution 2 - Angular

The Günter Zöchbauer's answer is correct. But if you, like I was, have troubles with rendering @Input data in the component template, you should try this:

  1. Run your component creating code in ngAfterViewInit.
  2. Add componentRef.instance.ngOnInit() as a last line.
  3. Inside ngOnInit of your dynamically created component run detectChanges method of the ChangeDetectorRef.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionbadger2013View Question on Stackoverflow
Solution 1 - AngularGünter ZöchbauerView Answer on Stackoverflow
Solution 2 - AngularEugene P.View Answer on Stackoverflow