2017-10-20 233 views
1

我的Angular 4應用程序使用第三方庫(mapbox)在頁面上呈現內容。該庫有一個彈出式對話框功能,允許當用戶點擊地圖上的一個引腳來顯示彈出窗口: https://www.mapbox.com/mapbox-gl-js/example/popup-on-click/任意位置在Angular 4/Force ViewChild檢測中的組件渲染

彈出叫做的東西,如下面的代碼:

map.on('click', 'places', function (e) { 
    new mapboxgl.Popup() 
     .setLngLat(e.features[0].geometry.coordinates) 
     .setHTML('<div>this is a popup</div>') 
     .addTo(map); 
}); 

我想將一個Angular 4+組件呈現到彈出式div中。我試過的東西:

1)將@ViewChild綁定到該彈出的div。

// in the component that holds the map component 
@ViewChild("pop", { read: ViewContainerRef }) childContainer: ViewContainerRef; 

//when the user clicks the popup 
popup.setHTML("<div #pop></div>") 

childContainer從未分配。我試過在彈出窗口打開後等待幾秒鐘,或者在組件的ChangeDetectorRef上調用detectChanges()。我試過在NgZone.runOutsideAngular()中打開彈出窗口,然後手動運行detectChanges()

如果我手動將div添加到我的html模板,彈出窗口按預期呈現到div的位置。

2)使用工廠到一個div與ID

//when the user clicks the popup 
popup.setHTML("<div id="pop">HERE</div>") 

const element = this.elRef.nativeElement.querySelector("#pop"); //this is found 
const factory = this.componentFactoryResolver.resolveComponentFactory(PopupComponent); 
const component = factory.create(this.viewContainerRef.injector, null, element); 

在div的內容該處與<!---->替換渲染它。很明顯,Angular會將的東西渲染到該位置,但不是實際的組件。我需要不同的注射器嗎?

3)放置部件渲染元素直接進入彈出:

popup.setHTML("<popup-component></popup-component>") 

它從未關閉自身成實際成分。即使有像detectChanges()NgZone這樣的東西也會運行。

4)有沒有其他想法?如何將Angular組件渲染到在Angular之外定義的任意html位置?

+0

你可以創建一個笨蛋。我相信你的複雜性可以很容易實現。 [**兒童模態與ViewChild **]的示例(https://stackoverflow.com/questions/42735858/ng2-bootstrap-show-hide-modal-as-child-component/42736058#42736058) – Aravind

回答

0

我能夠使用標準.append呼叫解決此問題。我不喜歡這個解決方案,但它似乎工作,沒有太多的缺點,所以我在這裏發佈它,以防其他人發現這個問題。

到同一頁面添加一個隱藏的組件爲您的地圖:由ID傳遞給信息流行組件類屬性

//map.component.html 
<div id="map"></div> 
<div style="display:none"> 
    <info-popup #infopop [id]="selectedId" [renderTo]="popupLocation"></info-popup>  
</div> 

綁定點擊彈出上述

//map.component.ts 
popupLocation: any; 
selectedId: any; 
initializeMap(): void { 
    this.map.on("click", "pinLayer", (e: MapMouseFeaturesEvent) => { 
    this.selectedId = e.features[0].properties["id"]; // assumes a distinct id per pin 
    new mapboxgl.Popup({ closeButton: false }) 
      .setLngLat(e.lngLat) 
      .setHTML("<div id='popupLocation'></div>") 
      .addTo(this.map); 
    this.popupLocation = this.elementRef.nativeElement.querySelector("#popupLocation); 
    }); 
} 

使用組件與追加:

//infopop.component.ts 
export class InfoPopupComponent implements OnChanges { 

    @Input() id: string; 
    @Input() renderTo: any; 
constructor(private elementRef: ElementRef) { } 


    ngOnChanges(changes: SimpleChanges): void { 
     if ("id" in changes) { 
      // load popup specific details and render 
     } 
     if (this.renderTo) { 
      this.renderTo.append(this.elementRef.nativeElement); 
     } 
    } 
} 

這與綁定的[click]事件infopop.component.ht毫升正確通過。