我怎么能从谷歌地图信息窗口调用Angular2函数呢?

How could I call a Angular2 function from a Google Map infowindow?

本文关键字:Angular2 调用 函数 窗口 信息窗 怎么能 谷歌地图 信息      更新时间:2023-09-26

Google map是以javascript的方式集成的,我想在一个信息窗口中调用angular2函数,如下面的代码所示。看看infoContent的按钮。

for (i = 0; i < locations.length; i++) {
  let locLatLng = new google.maps.LatLng(locations[i].latitude, locations[i].longitude);
  let infoContent = '<button (click)="myFunction(' + locations[i].id + ')">Details ...</button>';
  marker = new google.maps.Marker({
    position: locLatLng,
    map: this.map
  });
  google.maps.event.addListener(marker, 'click', (function(marker, i) {
    return function() {
      infowindow.setContent(infoContent);
      infowindow.open(this.map, marker);
    };
  })(marker, i));
}

不幸的是,角点击事件(click)="myFunction()"不能做到这一点。一定有别的办法。如果有人能给我指出正确的方向,我会很高兴的。

你可以在根窗口中实例化对ngZone的引用,并在infoWindow中调用它。

首先你需要在构造器中访问NgZone:

 constructor(public _ngZone: NgZone) {    }

然后你可以设置一个指针回到你的区域在窗口,在ngOnInit,构造函数或其他地方,取决于你的代码:

    window["angularComponentRef"] = { component: this, zone: this._ngZone };

最后你可以用zone.run从infoWindow回调到你的Angular函数,像这样:

    for (i = 0; i < locations.length; i++) {
        let locLatLng = new google.maps.LatLng(locations[i].latitude, locations[i].longitude);
        let infoContent: string = '<button onclick="window.angularComponentRef.zone.run(() => {window.angularComponentRef.component.myFunction(''' + locations[i].id + ''');})">Details ...</button>';
        marker = new google.maps.Marker({
            position: locLatLng,
            map: this.map
        });
        google.maps.event.addListener(marker, 'click', (function (marker, i) {
            return function () {
                infowindow.setContent(infoContent);
                infowindow.open(this.map, marker);
            };
        })(marker, i));
    }

你可以在需要的时候清理函数,避免污染窗口命名空间,在ngOnDestroy上,例如:

 window["angularComponentRef"] = null;

更新(评论)

你可以用ElementRefRenderer做,但这不是问题。问题是获取按钮的引用(直接DOM元素引用或ElementRef)。你可以注入private elRef:ElementRef并使用this.elRef.nativeElement.querySelector('infowindow button')或类似的东西,但如果你访问elRef.nativeElement,你就又脱离了平台中立的领域,因为nativeElement不应该被直接访问,但是Renderer的限制是只能调用方法,但永远不会得到返回的结果,你能做的只有这么多。

我会使用类似于infoWindow或InfoBox的触发事件中所示的方法,单击Google Map API V3,然后检查event.target,如果您感兴趣的元素被单击。

原来

如果你想在事件处理程序中访问this.map,你应该使用箭头函数代替

  google.maps.event.addListener(marker, 'click', ((marker, i) => { // <<<===
    return () => { // <<<===
      infowindow.setContent(infoContent);
      infowindow.open(this.map, marker);
    };
  })(marker, i)

否则this.不会指向当前的类实例

这是我的解决方案。首先,我将id设置为信息窗口中的按钮。在那之后,我捕获了信息窗口的domready事件,这意味着:所有的HTML都被浏览器接收并解析到DOM树中,现在可以进行操作了。然后用getElementById访问按钮并添加事件'click'。这里你可以调用在ts文件中定义的函数。

const infoWindowContent = '<h6>' + community.typeOfCommunity + '</h6>' +
          '<p>' + community.address.name + ' ' + community.streetNumber + ', ' + community.city + '</p>' +
          '<p>Manager: ' + community.manager.fullName + '</p>' +
          '<button  id="infoWindowButton">More info</button>';
        const infoWindow = new google.maps.InfoWindow({
          content: infoWindowContent
        });
        marker.addListener('click', () => {
          infoWindow.open(this.map, marker);
        });
        infoWindow.addListener('domready', () => {
          document.getElementById("infoWindowButton").addEventListener("click", () => {
            this.myFunction();
          });
        });

请尝试这个完整的解决方案。

var infowindow = new google.maps.InfoWindow({});
    for (i = 0; i < locations.length; i++) {
        let locLatLng = new google.maps.LatLng(locations[i].latitude, locations[i].longitude);
        let infoContent = '<div style="padding: 0.5em;">' +
            '<h5 id="lt" style="font-size: 12px">'+locations[i].id +'</h5>'+
            '<button id="btn" style="font-size: 8px;" >Click</button>'+
            '</div>'
        marker = new google.maps.Marker({
            position: locLatLng,
            map: this.map
        });
        google.maps.event.addListener(marker, 'click', (function(marker, i) {
            return function() {
                infowindow.setContent(infoContent);
                infowindow.open(this.map, marker);
            };
        })(marker, i));
    }
    infowindow.addListener('domready', () => {
        var val = document.getElementById('lt').innerHTML;
        document.getElementById("btn").addEventListener("click", () => {
            this.myFunction(val);
        });
    });

我搜索了很多,找到了答案:

必须使用:$compile(htmlString)(scope)

在你的例子中试试:

var infoContent = '<button ng-click="myFunction(' + locations[i].id + ')">Details</button>';
var scope = angular.element(document.getElementById('anyElementId')).scope();
var compiled = $compile(htmlElement)(scope);

然后使用:

infowindow.setContent(compiled[0]);

Wala !