好的,感谢@ghybs的建议,我又尝试了一次那个链接,并成功解决了问题:D。 Leaflet与Google Maps有点不同(也更短),提出的解决方案可能会更小,更易于理解,因此这是我使用Leaflet的版本。
基本上,您需要将弹出窗口组件放入主应用程序模块的entryComponents
字段中。关键内容在m.onclick()
中,我们在那里创建一个组件,在div
内呈现它,然后将该div
的内容传递给leaflet弹出窗口容器元素。有点棘手,但它可以工作。
我花了一些时间将此解决方案转换为Angular 4的新$compile。在此处查看详细信息。感谢@yurzui!:)
这是核心代码...其他内容(css、webpack等)与OP相同,简化为几个文件:https://github.com/darkguy2008/leaflet-angular4-issue,但只需要这个示例即可使其正常工作:
import 'leaflet';
import './main.scss';
import "reflect-metadata";
import "zone.js/dist/zone";
import "zone.js/dist/long-stack-trace-zone";
import { BrowserModule } from "@angular/platform-browser";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { Component, NgModule, ComponentRef, Injector, ApplicationRef, ComponentFactoryResolver, Injectable, NgZone } from "@angular/core";
@Component({
selector: "app",
template: `<section class="app"><map></map></section>`
})
class AppComponent { }
@Component({
selector: "popup",
template: `<section class="popup">Popup Component! :D {{ param }}</section>`
})
class PopupComponent { }
@Injectable()
class MapService {
map: any;
baseMaps: any;
markersLayer: any;
public injector: Injector;
public appRef: ApplicationRef;
public resolver: ComponentFactoryResolver;
public compRef: any;
public component: any;
counter: number;
init(selector) {
this.baseMaps = {
CartoDB: L.tileLayer("http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png", {
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> © <a href="http://cartodb.com/attributions">CartoDB</a>'
})
};
L.Icon.Default.imagePath = '.';
L.Icon.Default.mergeOptions({
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});
this.map = L.map(selector);
this.baseMaps.CartoDB.addTo(this.map);
this.map.setView([51.505, -0.09], 13);
this.markersLayer = new L.FeatureGroup(null);
this.markersLayer.clearLayers();
this.markersLayer.addTo(this.map);
}
addMarker() {
var m = L.marker([51.510, -0.09]);
m.bindTooltip('Angular 4 marker (PopupComponent)');
m.bindPopup(null);
m.on('click', (e) => {
if (this.compRef) this.compRef.destroy();
const compFactory = this.resolver.resolveComponentFactory(this.component);
this.compRef = compFactory.create(this.injector);
this.compRef.instance.param = 0;
setInterval(() => this.compRef.instance.param++, 1000);
this.appRef.attachView(this.compRef.hostView);
this.compRef.onDestroy(() => {
this.appRef.detachView(this.compRef.hostView);
});
let div = document.createElement('div');
div.appendChild(this.compRef.location.nativeElement);
m.setPopupContent(div);
});
this.markersLayer.addLayer(m);
return m;
}
}
@Component({
selector: "map",
template: `<section class="map"><div id="map"></div></section>`,
})
class MapComponent {
marker: any;
compRef: ComponentRef<PopupComponent>;
constructor(
private mapService: MapService,
private injector: Injector,
private appRef: ApplicationRef,
private resolver: ComponentFactoryResolver
) { }
ngOnInit() {
this.mapService.init('map');
this.mapService.component = PopupComponent;
this.mapService.appRef = this.appRef;
this.mapService.compRef = this.compRef;
this.mapService.injector = this.injector;
this.mapService.resolver = this.resolver;
this.marker = this.mapService.addMarker();
}
}
@NgModule({
imports: [
BrowserModule
],
providers: [
MapService
],
declarations: [
AppComponent,
MapComponent,
PopupComponent
],
entryComponents: [
PopupComponent
],
bootstrap: [AppComponent]
})
class AppModule { }
platformBrowserDynamic().bootstrapModule(AppModule);