最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular - How do directives "see" template & ViewContainer? - Stack Overflow

programmeradmin2浏览0评论

I have a simple ponent 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 ponents/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 ?

I have a simple ponent 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 ponents/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

Share Improve this question edited Jul 6, 2022 at 8:11 Alessandro_Russo 2,2311 gold badge28 silver badges37 bronze badges asked May 30, 2017 at 10:21 Royi NamirRoyi Namir 149k144 gold badges492 silver badges829 bronze badges 1
  • 1 you might find this article useful – Max Koretskyi Commented May 30, 2017 at 12:57
Add a ment  | 

1 Answer 1

Reset to default 8

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 ment 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 ment 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 ment 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    Hooray\n']))],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 Hooray\n

Angular uses such ViewDefinitions which are located in ngfactories to build the DOM tree

See also

  • Angular2: How is ngfor expanded

  • https://github./angular/angular/blob/4.2.0-rc.1/packages/core/src/linker/view_ref.ts#L41-L79

Don't forget to watch https://www.youtube./watch?v=EMjTp12VbQ8

发布评论

评论列表(0)

  1. 暂无评论