How do you use @Input with components created with a ComponentFactoryResolver?
AngularAngular 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:
- Run your component creating code in
ngAfterViewInit
. - Add
componentRef.instance.ngOnInit()
as a last line. - Inside
ngOnInit
of your dynamically created component rundetectChanges
method of theChangeDetectorRef
.