如何在Leaflet标记的弹出窗口中生成Angular 4组件?

时间:2017-07-13 21:38:31

标签: angular leaflet web-component

我一直是一个很长的Angular 1.x用户,现在我正在使用Angular 4创建一个新的应用程序。我仍然没有掌握大部分概念,但我终于有一些非常好的工作。但是,我有一个问题,我需要使用Leaflet在Marker的弹出窗口中显示Angular 4组件(尽管在1.x中我只是使用了指令)。

现在,在Angular 1.x中,我可以使用$ compile对其中带有指令的模板(`<component>{{ text }}</component>`)使用按钮等,并且它可以工作,但Angular 4与其AoT事物完全不同并且在运行时编译似乎非常困难,并且没有简单的解决方案。

我问了一个问题here,作者说我可以使用指令。我不确定这是否是正确的方法,甚至不知道如何将我自己的代码与他提出的解决方案混合...所以我做了一个基于npm的小项目,Angular 4和Leaflet已经设置好,以防你知道如何帮助我还是想试一试(我非常感谢!)。我一直在喋喋不休地谈论这个问题可能已经有一个星期了,我真的厌倦了尝试很多替代品而没有成功:(

以下是我在GitHub中的回购链接:https://github.com/darkguy2008/leaflet-angular4-issue

我们的想法是在Marker中生成PopupComponent(或类似的东西),代码可以在src / app / services / map.service.ts,第38行找到。

提前致谢! :)

修改

我设法解决了:)看到标记答案的细节,或者这个差异。有一些注意事项,Angular 4和Leaflet的过程略有不同,并且不需要进行太多更改:https://github.com/darkguy2008/leaflet-angular4-issue/commit/b5e3881ffc9889645f2ae7e65f4eed4d4db6779b

我还用这个解决方案here解决了自定义编译服务并上传到同一个GitHub存储库。谢谢@yurzui! :)

2 个答案:

答案 0 :(得分:11)

好吧,感谢@ ghybs的建议,我给了那个链接另一个尝试并设法解决了这个问题:D。 Leaflet与谷歌地图略有不同(它也更短),建议的解决方案可能会更小,更容易理解,所以这是我使用Leaflet的版本。

基本上,您需要将弹出窗口组件放在主应用程序模块的self.hideMarkers = function() { for (var i = 0; i < markers.length; i++) { markers[i].setMap(null); } }; 字段中。关键的东西是entryComponents,在那里,我们创建一个组件,在m.onclick()内渲染它,然后我们将div的内容传递给leaflet popup容器元素。有点棘手,但它确实有效。

我有时间将此解决方案转换为Angular 4的新$ compile。查看详细信息here。谢谢@yurzui! :)

这是核心代码......其他东西(css,webpack等)和OP在同一个repo中,简化为几个文件:https://github.com/darkguy2008/leaflet-angular4-issue但你只需要这个例子就可以了工作:

div

答案 1 :(得分:0)

  1. 如果您还没有弹出窗口,则需要为它创建一个组件。让我们假设它被称为MycustomPopupComponent
  2. 将您的组件添加到输入组件数组中的app.module.ts。动态创建组件时需要这样做:
   entryComponents: [
      ...,
      MycustomPopupComponent
   ],
  1. 在屏幕上,将以下两个依赖项添加到构造函数中:
constructor(
    ...
    private componentFactoryResolver: ComponentFactoryResolver,
    private injector: Injector
) {
  1. 现在在该屏幕上,我们可以定义一个动态创建组件的函数。
private createCustomPopup() { 
    const factory = this.componentFactoryResolver.resolveComponentFactory(MycustomPopupComponent);
    const component = factory.create(this.injector);

    //Set the component inputs manually 
    component.instance.someinput1 = "example";
    component.instance.someinput2 = "example";

    //Subscribe to the components outputs manually (if any)        
    component.instance.someoutput.subscribe(() => console.log("output handler fired"));

    //Manually invoke change detection, automatic wont work, but this is Ok if the component doesn't change
    component.changeDetectorRef.detectChanges();

    return component.location.nativeElement;
}
  1. 最后,在创建Leaflet弹出窗口时,将该函数作为参数传递给bindPopup。该函数还接受带有选项的第二个参数。
const marker = L.marker([latitude, longitude]).addTo(this.map);
marker.bindPopup(() => this.createCustomPopup()).openPopup();