I have a simple component which injects numbers after a delay via custom directive named *appDelay
I already know that *
is a hint for Angular to de-sugar the syntax into something like
<ng-template ...> ...actual markup </ng-template>
I also know that we can Inject components/templates to the viewContainer
via :
this.viewContainerRef.createEmbeddedView/Component(this.templateRef);
The directive code is :
@Directive({ selector: '[appDelay]' }) export class DelayDirective { constructor( private templateRef: TemplateRef<any>, private viewContainerRef: ViewContainerRef ) { } @Input() set appDelay(time: number): void { setTimeout(()=>{ this.viewContainerRef.createEmbeddedView(this.templateRef); }, time); } }
The docs states :
To access a ViewContainerRef of an Element, you can either place a Directive injected with ViewContainerRef on the Element, or you obtain it via a ViewChild query.
Question:
In a general pseudo form : What are the template “string values” for templateRef
and viewContainerRef
?
IMHO the de-sugared template would be something like:
<ng-template ...> <card *appDelay="500 * item"> {{item}} </card> </ng-template>
So the ViewContainerRef
would be a reference to <ng-template ...>
And the templateRef will be a reference to the <card >...</card>
— Is that correct ?
(Also , is it possible to console.log()
those HTML templates and see the actual markup ?
https://plnkr.co/edit/80AGn8bR4CiyH0ceP8ws?p=preview
Advertisement
Answer
ViewContainerRef
just point to element that will be host for inserting views. Those views will be added as siblings to this host element.
For structural directive comment like <!---->
will be host element.
Desugar for
<div *appDelay="500"> Hooray </div>
will be
<ng-template [appDelay]="500"> <div> Hooray </div> </ng-template>
it also can be described like so:
<ng-template view-container-ref></ng-template> <!-- ViewRef --> <div> Hooray </div> <!-- /ViewRef -->
Since ng-template
is not stamped to the DOM it will be rendered as <!---->
.
Angular will create ViewContainerRef
with reference to this comment tag.
vcRef.element.nativeElement
Each ViewContainer can have only one anchor element and each anchor element can only have a single ViewContainer. ViewContainer is a container that helps you to manipulate Views(ViewRef
, EmbeddedViewRef
)
Also TemplateRef
instance will be created
class TemplateRef_ { constructor(private _parentView: ViewData, private _def: NodeDef) { } get elementRef(): ElementRef { return new ElementRef(asElementData(this._parentView, this._def.index).renderElement); }
and its elementRef
(anchor or location) will point to the same comment element.
The main feature of TemplateRef is having template
property
this.templateRef._def.element.template
This property doesn’t contains html string but describes view
this.templateRef._def.element.template.factory + ''
will print
"function View_AppComponent_1(_l) { return jit_viewDef1(0,[(_l()(),jit_elementDef2(0,null,null,1,'div',[],null,null, null,null,null)),(_l()(),jit_textDef3(null,['n Hoorayn']))],null,null); }"
so this is our template. As you can see it describes view with div
root element and child text node with text n Hoorayn
Angular uses such ViewDefinitions
which are located in ngfactories
to build the DOM tree
See also
Don’t forget to watch https://www.youtube.com/watch?v=EMjTp12VbQ8