Angular 2/Leaflet map,如何从标记弹出窗口链接到组件?...路由器链接? [英] Angular 2 / leaflet map, How to link to a component from marker popup ? ... routerLink?

查看:28
本文介绍了Angular 2/Leaflet map,如何从标记弹出窗口链接到组件?...路由器链接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 angular 2 应用程序中,我有一个传单地图,其中有一个绑定到 onClick 事件的弹出窗口.

Inside my angular 2 app I have a leaflet map with a popup bound to a onClick event.

弹出窗口的内容有一个指向角度组件的链接.但是,当我在 .setContent() 函数中使用 routerLink 时,链接不会显示.

The content of the popup has a link to an angular component. however when I use routerLink inside the .setContent() function the link doesn't show.

我猜这是因为 .setContent() 无法呈现有意义的 angular 2 指令.我可以用什么代替?

I'm guessing this is happening because .setContent() is not able to render angular 2 directives which makes sense. what can I use instead?

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.css']
})

export class MapComponent implements AfterViewInit {

  openmap: any;

  constructor() { }

  ngAfterViewInit() {

    let openmap = L.tileLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}", {
      attribution: 'terms and feedback'
    });

    let map = L.map("map", {
      center: [33.2148, -97.1331],
      zoom: 5,
      zoomControl: true,
      maxZoom: 18 
    }).addLayer(openmap);

    let marker = L.marker([39.2148, -98.1331]).addTo(map);

    let popup = L.popup();

    function onMapClick(e) {
      popup
        .setLatLng(e.latlng)
        .setContent("Facility" + "<br/>" + "<a routerLink='/view2'>" + "View Two" + "</a>")
        .openOn(map);
    }

    map.on('click', onMapClick);
  }

}

针,再说如果我改成

 .setContent("Facility" + "<br/>" + "<a href='../view2'>" + "View Two" + "</a>")

会做我想做的,但这会导致页面刷新,所以这不是一个选项.

Will do what I want, but this will cause a page refresh, so this is not an option.

推荐答案

有一个非常简单的方法,也有一个非常复杂的方法.

There is a very simple approach and a very complex one.

简单的方法是在没有 RouterLink 的情况下使用带有 angular 之外的锚元素的原始 HTML.注册点击该锚点元素并使用路由器服务进行导航.

The simple approach is to use raw HTML with anchor element outside of angular without RouterLink. Register to clicks on that anchor element and use the Router service to navigate.

任务是触发链接,但实际问题要深得多,现在它下次显示角度分量时链接...

The task was to fire links but the actual problem is far deeper, now it links next time its showing an angular component...

所以,对于复杂的解决方案:

So, for the complex solution:

这是一个非常高级的主题......它不仅涉及使用高级角度技术,而且在传单实施方面也很先进.

This is an highly advanced topic... Not only it involves using advanced angular techniques it's also advanced in the leaflet implementation.

我会尽我所能传达信息,但由于复杂性,示例将非常简单并且需要工作.

I'll do my best to convey the message but due to the complexity the examples will be very simple and will require work.

包含指令、组件或管道的 HTML 字符串永远不会工作,唯一的方法是初始化一个 View

An HTML string that contains directives, components or pipes will never work, the only way is to initialize a View

让我们将 View 定义为对 组件模板 的视图实例的引用.

Let's define A View as a reference to view instance of a component or a template.

这些被称为 ComponentRefTemplateRef

所以,我们有两种方法来解决这个问题.由于我不能同时使用 ComponentRef,但请注意,您也可以使用 TemplateRef.对于模板,您首先需要获取组件中定义的模板以及要附加该模板的 ViewContainerRef.

So, we have 2 ways to solve this problem. Since I can't do both i'll go with ComponentRef but note that you can also use TemplateRef. With templates you'll first need to obtain a template defined in the component as well as a ViewContainerRef to attach that template to.

我们将构建一个接受传单 Marker 并绑定到标记的点击事件的服务,点击它会打开一个弹出窗口,它是一个角度组件.

We will build a service that accepts a leaflet Marker and binds to the click event of the marker, on click it will open a popup which is an angular Component.

组件很简单,它呈现一个链接.

The component is simple, it renders a link.

@Component({
  selector: 'facility-link',
  template: `Facility <br/> <a routerLink="{{link}}"> View Two</a>`
})
export class FacilityLinkComponent {
  public link: string;
  constructor() { }
}

现在,对于服务:

@Injectable()
export class LinkPopupService {

  constructor(private cfr: ComponentFactoryResolver,
              private injector: Injector,
              private appRef: ApplicationRef) { }


  register(marker: leaflet.Marker, link: string): void  {
    marker.on('click', ($event: leaflet.MouseEvent)  => this.popup($event.target, link) );
  }

  popup(marker: leaflet.Marker, link: string) {
    const cmpFactory = this.cfr.resolveComponentFactory(FacilityLinkComponent);
    const componentRef = cmpFactory.create(this.injector);
    componentRef.instance.link = link;
    this.appRef.attachView(componentRef.hostView);
    const markerElement = marker.getElement();
    markerElement.parentElement.appendChild(componentRef.location.nativeElement);

    const markerPos = leaflet.DomUtil.getPosition(markerElement);
    const markerClass = leaflet.DomUtil.getClass(markerElement);


    leaflet.DomUtil.setTransform(componentRef.location.nativeElement, markerPos);
    leaflet.DomUtil.setClass(componentRef.location.nativeElement, markerClass);
  }
}

register 方法接受一个标记和链接并注册到点击事件.

The register method accepts a marker and the link and registers to the click event.

popup 方法触发时,它使用角度工具创建 FacilityLinkComponent 的视图实例,设置链接以供将来绑定,将视图附加到它并将其附加到DOM.

When the popup method fires it uses angular tools to create a view instance of FacilityLinkComponent, set the link for future binding, attach a view to it and attach it to the DOM.

这一切都发生在前 5 行代码中.

This all happens in the first 5 lines of code.

一些注意事项:

  • 我们必须附加一个视图,以便更改检测工作
  • 正确的实现将允许设置 ViewContainerRef 和/或 Injector - 这是使用延迟加载时必须的.
  • 最好通过 Injector 而不是通过赋值 (ReflectiveInjector) 向组件发送数据
  • 需要适当的清理(销毁组件并分离视图)
  • 需要添加切换逻辑,导航也很干净.
  • We must attach a view so change detection works
  • A Proper implementation will allow to set ViewContainerRef and / or an Injector - this is a must when using lazy loading.
  • It is preferred sending data to the component via Injector and not by assignment (ReflectiveInjector)
  • Proper clean up is required (destroy the component and detach the view)
  • Need to add toggle logic, also clean on navigation.

第 6 行的代码执行弹出窗口的定位.

The code from the 6th line performs positioning of the popup.

这是一个非常简单的逻辑,它只是从标记中复制所有内容.

This is a very simple logic, it just copies everything from the marker.

这就是我使用标记的原因,所以我会有一个参考来获取定位.

This is why I used a marker, so I'll have a reference to take the positioning from.

在实际示例中,您需要获取一个面板并将组件推入它们自己的层,计算位置.这并不难,因为传单有所有的帮手,但它太多了.

In a realworld example you'll need to get a panel and push the components into their own layer, computing the position. This is not that difficult since leaflet has all the helper, but it was too much for this.

希望有帮助.

这篇关于Angular 2/Leaflet map,如何从标记弹出窗口链接到组件?...路由器链接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆