2017-10-20 136 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毫升正确通过。