14

我正在尝试包含一个模板文件views/infowindow.html作为我为启动 google maps api 而编写的服务中的 InfoWindow 的内容:

for ( var count = locations.length, i = 0; i < count; i++ ) {

  var latLng  = locations[i],
    marker = new google.maps.Marker({
      …
    }),
    infowindow = new google.maps.InfoWindow();

  google.maps.event.addListener(
    marker,
    'click',
    (function( marker , latLng ){
      return function(){
        var content = '<div ng-include src="\'infowindow.html\'"></div>';
        infowindow.setContent( content );
        infowindow.open( Map , marker );
      }//return fn()
    })( marker , latLng )
  );//addListener

}//for

content但是,当 Angular插入 InfoWindow 时,它似乎没有处理(当通过开发工具检查代码时,插入的代码是<div ng-include src="'views/infowindow.html'"></div>)。

我希望 Angular 在将我的包含插入到 InfoWindow 之前对其进行预处理,但可惜没有。

我正在尝试做的事情可能吗?

我在想,在将模板传递给之前,我必须以某种方式缓存模板infowindow.setContent(),但我不知道该怎么做(或者如果这甚至是我应该做的)。我宁愿在事件上加载模板,而不是为每个标记缓存和注入它。

编辑查看 $templateCache 和相关的 SO question

编辑 2这是一个尝试使用的plunk$compile(InfoWindow 的内容仍然是<div id="infowindow_content" ng-include src="'infowindow.html'"></div>


解决方案

其基础来自马克的回答如下。在他的解决方案中,InfoWindow 的内容在第一次单击(任何标记)时编译,但 InfoWindow 直到再次单击任何标记时才真正打开,可能是因为 GoogleMaps 不耐烦。

移到$compile外面,然后把编译好的模板传进去就 .addListener解决了这个问题:

for ( … ) {
  …
  infowindow = new google.maps.InfoWindow();
  scope.markers …
  var content = '<div id="infowindow_content" ng-include src="\'infowindow.html\'"></div>';
  var compiled = $compile(content)(scope);

  google.maps.event.addListener(
    marker,
    'click',
    (function( marker , scope, compiled , localLatLng ){
      return function(){
        scope.latLng = localLatLng;//to make data available to template
        scope.$apply();//must be inside write new values for each marker
        infowindow.setContent( compiled[0].innerHTML );
        infowindow.open( Map , marker );
      };//return fn()
    })( marker , scope, compiled , scope.markers[i].locations )
  );//addListener

}//for

更新了 Plunker

4

3 回答 3

13

添加content到 DOM 后,您需要找到它(可能使用 jQquery 选择器?),然后$compile() 并将其应用到适当的范围。这将导致 Angular 解析您的内容并根据它找到的任何指令(如 ng-include)采取行动。

例如,$compile(foundElement)(scope)

没有更多的代码,很难给出更准确的答案。但是,您可以查看类似的问题和答案。

更新:好的,我终于让它工作了,我学到了一些东西。

google.maps.event.addListener(
      marker,
      'click',
      (function( marker , scope, localLatLng ){
        return function(){
          var content = '<div id="infowindow_content" ng-include src="\'infowindow.html\'"></div>';
          scope.latLng = localLatLng;
          var compiled = $compile(content)(scope);
          scope.$apply();
          infowindow.setContent( compiled[0].innerHTML );
          infowindow.open( Map , marker );
        };//return fn()
      })( marker , scope, scope.markers[i].locations )

我的印象是只有 DOM 元素可以被 $compiled —— 即,我首先必须将内容添加到 DOM,然后编译它。事实证明这不是真的。content上面,我首先针对 进行编译scope,然后将其添加到 DOM 中。(我不知道这是否会破坏数据绑定——即由 $compile 设置的 $watch()es。)我必须设置scope.latLng,因为包含 ng 的模板需要插入{{latLng[0]}}{{latLng[1]}}. 我使用innerHTML而不是outerHTML只插入 infowindow.html 的内容。

笨蛋

更新2: 第一次点击不起作用。似乎直到第二次单击才加载“infowindow.html”(我尝试再次调用 scope.$apply() ......没有帮助)。当我让 plunker 工作时,我在 index.html 中内联了 infowindow.html 的内容:

<script type="text/ng-template" id="/test.html">
  <h4>{{latLng[0]}},{{latLng[1]}}</h4>
</script>

我在 addListener() 中使用它:

var content = '<div id="infowindow_content" ng-include src="\'/test.html\'"></div>';

我将 plunker 更改为使用内联模板。

于 2013-01-09T05:08:00.037 回答
8

上面的答案是可靠的,但是您失去了对以下内容的约束:

infowindow.setContent( compiled[0].innerHTML );

改为这样做:

infowindow.setContent( compiled[0] );

否则,如果您有类似<div>{{myVar}}</div>的内容,如果在您的应用程序中更新,它将不会更新myVar

于 2014-10-28T20:18:51.100 回答
1

你试过编译功能吗?http://docs.angularjs.org/api/ng.$compile

我还没有过多地研究角度,但我认为这可以工作。

或者,您可以尝试引导这些东西。但我不相信这是正确的方法...... http://docs.angularjs.org/guide/bootstrap

于 2013-01-09T01:43:06.510 回答