Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

angular

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.

like image 449
badger2013 Avatar asked Sep 01 '16 20:09

badger2013


People also ask

How do I use ComponentFactoryResolver?

ComponentFactoryResolverlinkUse to obtain the factory for a given component type, then use the factory's create() method to create a component of that type. Deprecated: Angular no longer requires Component factories. Please use other APIs where Component class can be used directly.

How do you use ViewContainerRef?

Access the ViewContainerRef of an element by placing a Directive injected with ViewContainerRef on the element, or use a ViewChild query. The dependency injector for this view container. Reports how many views are currently attached to this container.


2 Answers

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); 
like image 50
Günter Zöchbauer Avatar answered Oct 10 '22 01:10

Günter Zöchbauer


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.
like image 45
Eugene P. Avatar answered Oct 10 '22 02:10

Eugene P.