Projectable nodes are the node elements ( i.e elements implementing the node interface ), which are "projected" or in other words, transcluded onto the ng-content
that we have in the template of our component.
For example we can create a node element the following way :
var myNode = document.createElement('div');
var text = document.createTextNode('this is my text');
myNode.appendChild(text);
Then we can use the above node, the following way :
constructor(private vcr:ViewContainerRef ) {
}
ngAfterViewInit() {
let cmpFactory = this.vcr.resolveComponentFactory(MyDynamicComponent);
let injector = this.vcr.parentInjector;
var myNode = document.createElement('div');
var text = document.createTextNode('this is my text');
myNode.appendChild(text);
this.vcr.createComponent(cmpFactory,0,injector,[ [ myNode ] ])
}
A two dimensional array is accepted for projected nodes as we can have multi-slot transclusion, that is more than one ng-content
.
Here is a full example of how to use the projectable nodes with ViewContainerRef#createComponent
. This example dynamically creates a component that has transclsion/ng-content in it:
import { Component, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
import { ComponentFactory,ComponentRef, Renderer } from '@angular/core';
@Component({
selector: 'sample',
template: '<ng-content></ng-content><ng-content></ng-content>'
})
export class Sample { }
@Component({
selector: 'demo',
template: '<p>Demo</p>',
entryComponents: [Sample]
})
export class DemoComponent {
constructor(private vcr: ViewContainerRef, private cfr: ComponentFactoryResolver, private r: Renderer) { }
ngAfterViewInit() {
let cmpFactory = this.cfr.resolveComponentFactory(Sample);
let injector = this.vcr.parentInjector;
let demoCompEl = this.vcr.element.nativeElement;
let projectedElA = this.r.createElement(demoCompEl,'p');
this.r.createText(projectedElA,'projectable content A');
this.r.detachView([projectedElA]);
let projectedElB = this.r.createElement(demoCompEl,'p');
this.r.createText(projectedElB,'projectable content B');
this.r.detachView([projectedElB]);
let projectedC = document.createElement('div');
let text = document.createTextNode('projectable content C');
projectedC.appendChild(text);
let cmpRef = this.vcr.createComponent(cmpFactory,0,injector,[[projectedElA],[projectedElB,projectedC]]);
}
}
Output :
Demo
projectable content A
projectable content B
projectable content C
The additonal thing to notice is that in the 2d array that we pass for projectable nodes, each 1d array entry has the root elements of a particular view that belong together/ will be rendered together in a single ng-content
block