AngularJS ng-包含在Google Maps InfoWindow中?

jac*_*cob 14 javascript include infowindow google-maps-api-3 angularjs

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

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
Run Code Online (Sandbox Code Playgroud)

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

我希望Angular在将它插入InfoWindow之前预先处理我的包,但是没有.

我正在尝试做什么?

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

编辑查看$ templateCache和一个相关的SO问题.

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


其基础来自Mark的答案如下.在他的解决方案中,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
Run Code Online (Sandbox Code Playgroud)

更新了Plunker.

Mar*_*cok 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 )
Run Code Online (Sandbox Code Playgroud)

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

Plunker.

Update2: 第一次点击不起作用.似乎'infowindow.html'在第二次点击之前没有加载(我试着调用范围.$ apply()第二次......没有帮助).当我让plunker工作时,我在index.html中内联了infowindow.html:

<script type="text/ng-template" id="/test.html">
  <h4>{{latLng[0]}},{{latLng[1]}}</h4>
</script>
Run Code Online (Sandbox Code Playgroud)

我在addListener()中使用它:

var content = '<div id="infowindow_content" ng-include src="\'/test.html\'"></div>';
Run Code Online (Sandbox Code Playgroud)

我更改了plunker以使用内联模板.


Eth*_*n C 8

上面的答案是可靠的,但你失去了你的约束力:

infowindow.setContent( compiled[0].innerHTML );
Run Code Online (Sandbox Code Playgroud)

改为:

infowindow.setContent( compiled[0] );
Run Code Online (Sandbox Code Playgroud)

否则,如果你有类似的东西<div>{{myVar}}</div>,如果myVar你的应用程序更新,它将不会更新.