关于 ng-template 通过 @input 传入另一个 Component 不能工作的问题调试
問題描述
本文設計到的代碼倉庫:https://github.com/wangzixi-diablo/ngDynamic
host Component:
<ng-template #paramTemplate><div>我是#paramTemplate里的 div 標簽</div> </ng-template><app-template-input inputTemplate='paramTemplate'></app-template-input>我期望把 id 為 paramTemplate 的模板實例傳入子 Component:app-template-input.
然而運行時 Chrome console 報錯:
這些錯誤沒有一個是在我書寫的代碼之內:
ERROR TypeError: templateRef.createEmbeddedView is not a function
at ViewContainerRef.createEmbeddedView (core.js:10190:45)
at NgTemplateOutlet.ngOnChanges (ng_template_outlet.ts:65:28)
at NgTemplateOutlet.rememberChangeHistoryAndInvokeOnChangesHook (core.js:2373:14)
at callHook (core.js:3285:14)
at callHooks (core.js:3251:17)
at executeInitAndCheckHooks (core.js:3203:9)
at refreshView (core.js:7395:21)
at refreshComponent (core.js:8527:13)
at refreshChildComponents (core.js:7186:9)
at refreshView (core.js:7430:13)
問題分析
從調用棧 ViewContainerRef.createEmbeddedView 開始分析。設置斷點開始調試:
重新刷新頁面,斷點觸發:
檢查變量 templateRef,發現它的值是一個字符串。
但是接下來的語句,需要調用 templateRef 的 createEmbeddedView 方法。顯然,string 類型的變量,其原型鏈上是不可能有這個方法的,所以報錯。
我們注意到,當前的調用棧,發生在 ngTemplateOutlet 的 ngOnChanges 方法內。
查看 app-template-input 的實現,發現 @Input 接收的數據類型為 TemplateRef,因為只有這個類型,才定義了 createEmbeddedView 方法。
我們的實現里,錯誤地給其傳入了一個字符串。
解決辦法
給屬性 inputTemplate 加上一對中括號,使用表達式綁定語法,這樣 paramTemplate 會被當作一個表達式執行,導致第 48 行的 paramTemplate 實例被傳給 @Input:
最后問題解決:
總結
這里我們用 ng-container 里包裹了一個結構指令 *ngTemplateOutlet.
看 app-template-input 的實現。
任何消費 TemplateInputComponent 的 parent Component,都需要給第 18 行的 @Input 賦一個模板實例。
賦值語法如下:
<app-template-input [inputTemplate]="paramTemplate"></app-template-input>看起來給 inputTemplate 賦值的內容 paramTemplate 是一個字符串,實際是一個表達式。
最后生成的源代碼:
這里使用 *ngTemplateOutlet,動態生成一個 template 實例。
也就是說,ng-template 用 # 定義的 id,和 ng-container, *ngTemplateOutlet 這三者是配合起來使用的。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的关于 ng-template 通过 @input 传入另一个 Component 不能工作的问题调试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 形容自己无奈的歌词
- 下一篇: “THINK思考”永不停歇:IBM Th