[英]How to call a function in <ng-template> let variable declaration Angular 4
[英]How to call ng-template by variable?
我檢查了: ViewChildren for ng-template and Access multiple viewchildren using @viewchild
但是我無法通過變量的值調用我的模板...
所以我的模板是這樣的:
<ng-container *ngFor="let feature of Object.values(features)">
<ng-container *ngTemplateOutlet="templates[feature]"></ng-container>
</ng-container>
<ng-template #myFeature>
Nothing to see here
</ng-template>
<ng-template #myOtherFeature>
Nothing to see here
</ng-template>
features
是一個枚舉,其值與我的模板名稱相匹配……然后在我的班級中,我嘗試像這樣獲取所有ViewChildren
:
export class SomeClass {
@ViewChildren(TemplateRef) templates: QueryList<TemplateRef<any>>;
}
所以這個想法是,我認為我應該能夠通過執行templates[feature]
來引用正確的模板,它應該產生類似templates['myFeature']
並給我正確的模板......但不是。
我該如何存檔?
由於您創建了不同的模板(不同的模板變量),您需要為每個模板創建不同的子視圖。 ViewChildren 僅在它們具有相同的模板引用變量時才起作用。 並且在您的代碼中的用法它將獲取每個模板實例,因為您正在傳遞TemplateRef
,它將獲取此類型的每個實例。
我創建了一個 stackblitz,它演示了這一點。
另請注意,您的模板實例僅在ngAfterViewInit()
上可用,在ngAfterViewInit()
之前它將是未定義的。
在ngAfterViewInit
內部進行了一些修補之后,我讓它按照我想要的方式工作。 有點難看,因為我需要使用setTimeout
並且我需要使用內部變量(不確定這是否是個好主意)...
這是一個stackblitz ,展示了動態模板選擇和變量值渲染。
簡而言之,這就是我是如何做到的,你需要三件事:
// to grab all the templates
@ViewChildren(TemplateRef) templates: QueryList<TemplateRef<any>>;
// to be use for template selection
templateMap: { [key: string]: TemplateRef<any> } = {};
// to avoid rendering during the first run when templateMap is not yet ready
templateMapReady = false;
然后在ngAfterViewInit
執行以下操作來構建templateMap
:
ngAfterViewInit(): void {
// setTimeout to bypass the ExpressionChangedAfterItHasBeenCheckedError
setTimeout(() => {
// loop through the fetched template
this.templates.toArray().forEach(t => {
// for those ng-template that has a #name, they will have references
const keys = Object.keys((t as any)._def.references);
if (keys.length === 1) {
// so we put these in the templateMap
this.templateMap[keys[0]] = t;
}
});
// now we change it to ready, so it would render it
this.templateMapReady = true;
});
}
ViewChildren指令將在ngAfterViewInit()之前存儲其值(請參閱this )。
Angular 首先檢查你的模板並發現templates
是undefined
。
然后它開始渲染視圖。 在這個過程中,它解析模板指令,如ViewChildren()
並調用ngAfterViewInit()
。
在這個過程中, templates
被設置,這意味着視圖現在處於不一致的狀態。
頁面的初始呈現導致頁面本身發生變化。
那就是當您收到臭名昭著的“表達式已更改...”錯誤時。
設置templates
時無法更改,因為它是由 Angular 編排的。
但是,您可以做的是使用另一個變量進行綁定,並在初始視圖渲染完成后將其設置為templates
。
嘗試在ngAfterViewInit()
設置我們的新變量將再次觸發“表達式已更改”錯誤,因為此生命周期鈎子本身是初始渲染的一部分。
解決方案是將ngAfterViewInit()
新變量的設置推遲到下一個 VM 輪次。
為此,我們可以簡單地使用不帶第二個參數的setTimeout()
:
export class AppComponent implements AfterViewInit {
@ViewChildren(TemplateRef) templates!: QueryList<TemplateRef<any>>;
features: TemplateRef<any>[] = [];
name = "Angular";
ngAfterViewInit() {
setTimeout(() => this.features = this.templates.toArray());
}
}
請參閱此堆棧閃電戰示例
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.