[英]How do I dynamically create components with third party library in Angular?
使用 Angular 10
SO上有很多與此類似的問題,但我還沒有找到一個可以回答我的情況的問題。
我希望有人可以指導我。
我正在使用第三方庫來顯示 360° 照片。 這個第三方庫有一個內置的 API 來顯示場景中的熱點。 只需為庫提供您想要成為熱點的元素,它就會處理 rest。
我的大部分工作都按預期工作,但有幾件沒有。
到目前為止,我正在動態生成我的組件,如下所示:
this._hotspotFactory = this.resolver.resolveComponentFactory(HotspotComponent);
const component = this._hotspotFactory.create(this.injector);
//Hydrate component with bunch of data
component.instance.id = data.id;
...
// Create the Hotspot with Third Party
// Calling this third party method injects the native element into the DOM.
// Passing the nativeElement in. Looks great at first glance.
const hotspot = this._scene.createHotspot(data, component.location.nativeElement);
this.appRef.attachView(component.hostView);
component.hostView.detectChanges();
if(component.instance.over.observers.length) {
hotspot.on('over', (evt) => {
this.zone.run(() => {
component.instance.over.emit(evt);
});
});
}
if(component.instance.out.observers.length) {
hotspot.on('out', (evt) => {
this.zone.run(() => {
component.instance.out.emit(evt);
});
});
}
if(component.instance.navigate.observers.length) {
hotspot.on('click', (evt) => {
this.zone.run(() => {
component.instance.navigate.emit(evt);
})
});
}
沒有拋出任何錯誤,我成功地看到了熱點應該在場景中的位置。 甚至HotspotComponent
模板中的數據插值也會按預期發生。
但是, [ngStyle]
綁定永遠不會導致HotspotComponent
中的動態樣式。
我 99% 確定這是因為組件中沒有進行更改檢測。
我使用this.appRef.attachView(component.hostView)
手動附加視圖,因為第三方負責將元素注入 DOM,而不是 Angular。 因此 Angular 需要了解它,以便執行更改檢測。
即使手動調用attachView
,我仍然認為 Angular 不知道視圖中的這個組件,因為 Angular Chrome 擴展調試器沒有在其開發工具中將其注冊為視圖中的已知組件......盡管看到它在屏幕上和 DOM 中。
我錯過了什么?
組件有什么變化檢測策略? 當一個組件被添加到視圖中時,它的生命周期鈎子將由 angular( ngOninit
, ngAfterContentInit
等) 觸發。 在這些中記錄一些內容,看看是否正在調用主題生命周期鈎子。 無論更改檢測策略如何,在組件添加到視圖后,都應在組件上進行一個更改檢測周期。
如果生命周期鈎子調用沒有發生,那么這意味着 angular 沒有參與將元素添加到 DOM。
似乎 angular 有一個生命周期掛鈎,正好適合您的用例'ngDoBootstrap' 。
由於我們無法調試您的完整源代碼,從您提到的信息看來,您嘗試附加到視圖的動態組件似乎不適用於 NgModule 中的 Angular。 angular 引導的每個組件都必須在 NgModule 中。
您可以使用'ngDoBootstrap'動態引導它。
它以下列方式使用:
ngDoBootstrap(appRef: ApplicationRef) {
this.fetchDataFromApi().then((componentName: string) => {
if (componentName === 'ComponentOne') {
appRef.bootstrap(ComponentOne);
} else {
appRef.bootstrap(ComponentTwo);
}
});
}
在您的情況下,您可以在將組件附加到視圖之前執行此操作。
...
appRef.bootstrap(component);
this.appRef.attachView(component.hostView);
component.hostView.detectChanges();
...
同樣的問題,即使我也在幾天前被卡住了。 這是我完整討論的地方。 您將獲得您正在尋找的完整答案StackOverflow 討論
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.