首页 文章

Angular 2 / leaflet map,如何从标记弹出窗口链接到组件? ... routerLink?

提问于
浏览
4

在我的角度2应用程序中,我有一个传单映射,弹出窗口绑定到onClick事件 .

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

我猜这种情况正在发生,因为.setContent()无法渲染有意义的angular 2指令 . 我可以用什么呢?

@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" + "
" + "<a routerLink='/view2'>" + "View Two" + "</a>") .openOn(map); } map.on('click', onMapClick); } }

针,如果我把它更改为

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

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

2 回答

  • 8

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

    简单的方法是使用带有锚点元素的原始HTML,而不使用 RouterLink . 注册以点击该锚元素并使用 Router 服务进行导航 .

    任务是发射链接,但实际问题更深入,现在它链接下次显示一个角度组件...

    因此,对于复杂的解决方案:

    这是一个非常高级的主题......不仅涉及使用先进的角度技术,它在传单实现中也是先进的 .

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

    第一 - Angular领域 .

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

    让我们将A View 定义为查看 componenttemplate 的实例的参考 .

    这些被称为 ComponentRefTemplateRef

    所以,我们有两种方法可以解决这个问题 . 因为我可以't do both i'与 ComponentRef 一起使用,但请注意您也可以使用 TemplateRef . 使用模板,您首先需要获取组件中定义的模板以及将模板附加到的 ViewContainerRef .

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

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

    @Component({
      selector: 'facility-link',
      template: `Facility 
    <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 方法接受标记和链接并注册到click事件 .

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

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

    一些说明:

    • 我们必须附加一个视图,以便更改检测工作

    • 正确的实现将允许设置 ViewContainerRef 和/或 Injector - 这是使用延迟加载时必须的 .

    • 首选通过Injector将数据发送到组件而不是通过赋值(ReflectiveInjector)

    • 需要正确清理(销毁组件并分离视图)

    • 需要添加切换逻辑,也可以在导航时清除 .

    传单

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

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

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

    在一个真实世界的例子中,你需要获得一个面板并将组件推入他们自己的层,计算位置 . 这并不困难,因为传单有所有的帮助,但它太多了 .

    希望能帮助到你 .

  • 0

    **这个答案不起作用 . 如果有人有解决方案,我会暂时搁置它 . 我认为它显示了Angular需要SafeHtml用于routerLink的问题(请参阅DomSanitizer),而Leaflet只会使用.setContent().bindPopup()将字符串传递给弹出窗口

    以下代码基于Sanitize input in Angular2

    export class MapComponent implements AfterViewInit {
    
      constructor(private _sanitizer: DomSanitizer){}
    
      private _popUpContent: string = '"Facility" + "
    " + "<a routerLink='/view2'>" + "View Two" + "</a>"'; private htmlProperty(): SafeHtml { return this._sanitizer.bypassSecurityTrustHtml(this._popUpContent); } ngAfterViewInit() { let safeLink = this.htmlProperty(); 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(safeLink) //throws type error .openOn(map); } map.on('click', onMapClick); } }

相关问题