15Angular templateRef和NgTemplate

2020-12-27  本文已影响0人  learninginto
templateRef

获取当前组件模板中的元素(组件、ng-template、dom)

{static:true}默认为false,控制在变更检测之前拿取实例。通常将其置为true,要求它在变更检测之后拿取。

有时在一个变更检测周期内,监听的数值会发生变化,可以将操作的内容转为异步执行

setTimeout(()=>{
    this.firstContain.createEmbeddedView(this.firstTpl);
},0)

创建一个视图,并把它附着到父视图的容器中

  // 获取模板中的元素(组件、ng-template、dom)
  @ViewChild('box') readonly boxEl: ElementRef;
  
  //template元素
  @ViewChild('firstTpl', { read: TemplateRef }) readonly firstTpl: TemplateRef<any>;
  @ViewChild('secondTpl', { read: TemplateRef }) readonly secondTpl: TemplateRef<any>;
  @ViewChild('thirdTpl', { read: TemplateRef }) readonly thirdTpl: TemplateRef<any>;
  @ViewChild('fourthTpl', { read: TemplateRef }) readonly fourTpl: TemplateRef<any>;
  @ViewChild('freeTpl', { read: TemplateRef }) readonly freeTpl: TemplateRef<any>;
  
  @ViewChild('firstContainer', { read: ViewContainerRef, static: true }) readonly firstContain: ViewContainerRef;
  @ViewChild('secondContainer', { read: ViewContainerRef, static: true }) readonly secondContain: ViewContainerRef;
  private freeViewRef: EmbeddedViewRef<any>;

firstTpl:TemplateRef<any>;

//DOM元素
@ViewChild('box')readonly boxEl:ElementRef;

//container
@ViewChild('firstContainer',{read:ViewContianerRef}) readonly firstContain : ViewContainerRef

ngAfterViewInit():void{
    console.log('ngAfterViewInit')
    console.log(this.firstTpl);
    //viewref.rootNodes下是当前dom节点里的元素
    this.boxEl.nativeElement.appendChild(viewref.rootNodes[0])
    
    //将firstTpl创建出来,插入到firstContainer中
    this.firstContain.createEmbeddedView(this.firstTpl)
}

  insert(tpl: TemplateRef<any>) {
    this.firstContain.insert(tpl.createEmbeddedView(null));
  }

  insertAll() {
    [this.secondTpl, this.thirdTpl, this.fourTpl].forEach(tpl => {
      this.firstContain.insert(tpl.createEmbeddedView(null));
    });
  }

  getOne() {
    console.log(this.firstContain.get(2));
    console.log(this.firstContain.indexOf(this.freeViewRef));
  }

  insertFree() {
    this.firstContain.insert(this.freeViewRef, 1);
  }

  move() {
    // 不需要事先插入也可以移动(定好位置再插入)
    this.firstContain.move(this.freeViewRef, 2);
  }

  move2To4() {
    const view = this.firstContain.detach(1);
    this.firstContain.insert(view, 3);
  }

  move2ToOther() {
    const view = this.firstContain.detach(1);
    this.secondContain.insert(view);
  }

<div class="box" #box>
  <button class="btn btn-primary mr-1" (click)="insert(secondTpl)">insert second</button>
  <button class="btn btn-primary mr-1" (click)="insert(thirdTpl)">insert third</button>
  <button class="btn btn-primary mr-1" (click)="insert(fourthTpl)">insert fourth</button>
  <button class="btn btn-primary mr-1" (click)="insertAll()">insert all</button>
  <button class="btn btn-secondary mr-1" (click)="insertFree()">insert free</button>
  <button class="btn btn-info mr-1" (click)="getOne()">get one</button>
  <button class="btn btn-success mr-1" (click)="move()">move free</button>
  <button class="btn btn-success mr-1" (click)="move2To4()">把第二个移动到第四个位置上</button>
  <button class="btn btn-success" (click)="move2ToOther()">把第二个移动到其他容器中</button>
  <p>长度:{{ firstContain?.length }}</p>
</div>
<ng-template #firstTpl>
  <p>first tpl content</p>
</ng-template>


<ng-template #secondTpl>
  <p>第二段template</p>
</ng-template>

<ng-template #thirdTpl>
  <p>第三段template</p>
</ng-template>

<ng-template #fourthTpl>
  <p>第四段template</p>
</ng-template>

<ng-template #freeTpl let-fr="free" let-def>
  <p>自由的template -- fr: {{ fr }} def: {{ def }}</p>
</ng-template>

<p>
  first container:
  <ng-container #firstContainer></ng-container>
</p>

<hr>

<p>
  second container:
  <ng-container #secondContainer></ng-container>
</p>
NgTemplateOutlet

根据一个提前备好的 TemplateRef 插入一个内嵌视图。

import { Component, Input, TemplateRef } from '@angular/core';
@Component({
  selector: 'app-tpl-outlet',
  template: `<div>
               <ng-container *ngTemplateOutlet="render || defaultTpl; context: myContext"></ng-container>
               <!--      <ng-container [ngTemplateOutlet]="render || defaultTpl" [ngTemplateOutletContext]="myContext"></ng-container>-->
               
               <!--   用在ng-template上也可以   -->
               <!--      <ng-template *ngTemplateOutlet="render || defaultTpl; context: myContext"></ng-template>-->
               <!--      <ng-template [ngTemplateOutlet]="render || defaultTpl" [ngTemplateOutletContext]="myContext"></ng-template>-->
             </div>
            <ng-template #customTpl let-def let-val="value">
              <b>customTpl rendered! def: {{ def }}; value: {{ val }}</b>
            </ng-template>`
})
export class TplOutletComponent  {
  @Input () render: TemplateRef<any>;
  myContext = {$implicit: 'World', value: 'Svet'};
}
import { Component, Input } from '@angular/core';
@Component({
  selector: 'app-root',
  template: `<app-tpl-outlet [render]="render"></app-tpl-outlet>
             <ng-template #render let-value="value">
               <p><b>自定义的dom -- {{ value }}</b></p>
             </ng-template>
          `
})
export class ItemDetailComponent  {

}
上一篇下一篇

猜你喜欢

热点阅读