# 動態生成Angular Component ### 動機 在預約視圖裡,用戶希望在週視圖的header的日期旁邊要有假期資訊,但fullcalendar不支援調整週視圖header,所以花了點時間研究。 > 有時候第三方套件本身沒有提供相關的API去調整UI的時候,此時便可以透過此方法自行插入component到指定的DOM上。 ### 舊的做法 在我寫這篇文章之前,我所知道的動態生成組件會需要兩個東西 * ~~[ComponentFactoryResolver (已棄用)](https://angular.io/api/core/ComponentFactoryResolver)~~ * [ViewContainerRef](https://angular.io/api/core/ViewContainerRef) > 具體使用範例方式可參考[此處](https://stackblitz.com/edit/angular-componentfactoryresolver-example?file=src%2Fapp%2Fapp.component.ts) 動態組件插入的位置看的是ViewContainerRef,如果今天插入的位置是第三方套件,我只拿的到它的DOM,那這時該怎麼辦呢 ### 解決方法 `@angular/core`有提供一個方法`createComponent()`,它能讓我們自行決定組件要插入的位置(透過DOM) --- 給fullcalendar的DOM掛上我們自己寫的Component ``` typescript /** * @param host 要掛到哪個目標DOM上 * @param tooltip 就是個tooltip */ dynamicAddTooltip(host: Element, tooltip: string) { // 這邊可以為任意的Element(不一定要是Text) const textNode = document.createTextNode(tooltip); // 創建Component const autoTooltipRef = createComponent(AutoTooltipComponent, { environmentInjector: this.applicationRef.injector, // 這邊對應的是組件內的<ng-content> projectableNodes: [[textNode]] }); // 調整組件內的@Input的值 autoTooltipRef.instance.maxLine = 1; // 讓這個動態生成的組件也能進到angular更新檢查機制裡 this.applicationRef.attachView(autoTooltipRef.hostView); // 把組件掛到第三方套件內指定的DOM上 host.appendChild(autoTooltipRef.location.nativeElement); } ``` > 補充說明: > applicationRef的來源是透過constructor注入進來的 > ``` typescript > import { ApplicationRef } from '@angular/core'; > > constructor(private applicationRef: ApplicationRef) {} > ``` ### 結果圖 ![](https://hackmd.io/_uploads/rkz4chpAh.png)