18

I would like to set the body of <ng-content> while instantiating a component dynamically using ComponentFactoryResolver.

I see that I can get access to input & output using ComponentRef, but not a way to set <ng-content>.

Please note <ng-content> I'm planning on setting can contain simple text/can span dynamically created components

@Component({ selector: 'app-component-to-project', template: `<ng-content></ng-content>` }) export class ComponentToProject implements AfterContentInit { ngAfterContentInit() { // We will do something important with content here } } @Directive({ selector: 'appProjectionMarker' }) export class ProjectionMarkerDirective implements OnInit { constructor(private viewContainerRef: ViewContainerRef, private componentFactoryResolver: ComponentFactoryResolver) { } ngOnInit() { const componentFactory: ComponentFactory<ComponentToProject> = this.componentFactoryResolver.resolveComponentFactory(ComponentToProject); const componentRef: ComponentRef<ComponentToProject> = this.viewContainerRef.createComponent(componentFactory); // Question: How to set content before the child's afterContentInit is invoked } } @Component({ selector: 'appTestComponent', template: `<div appProjectionMarker></div>` }) export class TestComponent {} 
7
  • 1
    Use projectableNodes parameter stackoverflow.com/questions/41372334/… Commented May 31, 2017 at 12:30
  • Can I add a dynamic component too as projectableNodes, so the child is available to directive's parent as @ContentChild? Commented May 31, 2017 at 12:38
  • Since it is a projectableNodes, I assume I can only pass DOM elements Commented May 31, 2017 at 12:40
  • No, you can inject component into it or template. But you should manipulate only nodes Commented May 31, 2017 at 12:44
  • 1
    See from 20.00 youtube.com/watch?v=EMjTp12VbQ8 Commented May 31, 2017 at 12:46

1 Answer 1

36

There is the projectableNodes parameter for the vcRef.createComponent method

createComponent<C>(componentFactory: ComponentFactory<C>, index?: number, injector?: Injector, projectableNodes?: any[][], ngModule?: NgModuleRef<any>): ComponentRef<C>; 

You can use it to dynamically inject one component into another.

Let's say we have the following component

@Component({ selector: 'card', template: ` <div class="card__top"> <h2>Creating a angular2 component with ng-content dynamically</h2> </div> <div class="card__body"> <ng-content></ng-content> </div> <div class="card__bottom"> <ng-content></ng-content> </div> ` }) export class CardComponent {} 

We want to create it dynamically and insert some controls to its ng-content locations. It could be done like follows:

const bodyFactory = this.cfr.resolveComponentFactory(CardBodyComponent); const footerFactory = this.cfr.resolveComponentFactory(CardFooterComponent); let bodyRef = this.vcRef.createComponent(bodyFactory); let footerRef = this.vcRef.createComponent(footerFactory); const cardFactory = this.cfr.resolveComponentFactory(CardComponent); const cardRef = this.vcRef.createComponent( cardFactory, 0, undefined, [ [bodyRef.location.nativeElement], [footerRef.location.nativeElement] ] ); 

Plunker Example

See also

Sign up to request clarification or add additional context in comments.

2 Comments

In this case you know beforehand that there are two ng-content, how could you know how many are there if the object is dynamically pass? I mean, if CardComponent can be any component?
I just found how to know the number of projections with ComponentFactory.ngContentSelectors so in this case cardFactory.ngContentSelectors.length

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.