templateRef
- ViewChild
获取当前组件模板中的元素(组件、ng-template、dom)
{static:true}默认为false,控制在变更检测之前拿取实例。通常将其置为true,要求它在变更检测之后拿取。
有时在一个变更检测周期内,监听的数值会发生变化,可以将操作的内容转为异步执行
setTimeout(()=>{
this.firstContain.createEmbeddedView(this.firstTpl);
},0)
- createEmbeddedView()
创建一个视图,并把它附着到父视图的容器中
// 获取模板中的元素(组件、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);
}
- html
<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'};
}
- 调用TplOutletComponent传入自定义的dom
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 {
}
网友评论