javascript AngularJS ng-include 在 Google Maps InfoWindow 中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14226975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 21:04:35  来源:igfitidea点击:

AngularJS ng-include inside of Google Maps InfoWindow?

javascriptgoogle-maps-api-3includeangularjsinfowindow

提问by jacob

I'm trying to include a template file views/infowindow.htmlas the content of my InfoWindow from service I wrote to initiate the google maps api:

我正在尝试将模板文件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

However, it seems that Angular is not processing contentwhen it is inserted into the InfoWindow (when inspecting the code via Dev Tools, the code that gets inserted is <div ng-include src="'views/infowindow.html'"></div>).

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

I was hoping Angular would pre-process my include before it was inserted into the InfoWindow, but alas no.

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

Is what I'm trying to do possible?

我正在尝试做的可能吗?

I'm thinking that I'll have to somehow cache the template before passing it to infowindow.setContent(), but I don't know how to do that (or if that's even what I shouldbe doing). I would prefer to load the template on the event instead of caching and injecting it for each marker.

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

EDITLooking at $templateCache and a related SO question.

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

EDIT 2Here's a plunkthat tries to use $compile(the content of InfoWindow is still <div id="infowindow_content" ng-include src="'infowindow.html'"></div>)

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



SOLUTION

解决方案

The basis for this came from Mark's answer below. In his solution, the content for InfoWindow is compiled on first click (of any marker) but the InfoWindow does not actually open until another click on any Marker, probably because GoogleMaps is impatient.

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

Moving the $compileoutside and then passing the compiled template into .addListenersolves this problem:

$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

Updated Plunker.

更新了 Plunker

采纳答案by Mark Rajcok

After you add the contentto the DOM, you'll need to find it (maybe with a jQquery selector?), then $compile() it and apply it to the appropriate scope. This will cause Angular to parse your content and act on any directives it finds (like ng-include).

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

E.g., $compile(foundElement)(scope)

例如, $compile(foundElement)(scope)

Without more code, it is difficult to give a more precise answer. However, here is a similar question and answeryou can look at.

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

Update:okay, I finally got this to work, and I learned a few things.

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

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 )

I was under the impression that only DOM elements could be $compiled -- i.e., that I first had to add the content to the DOM, and then compile it. It turns out that is not true. Above, I first compile contentagainst the scope, and then add it to the DOM. (I don't know if this might break databinding -- i.e., the $watch()es that were set up by $compile.) I had to set scope.latLngbecause the ng-included template needs to interpolate {{latLng[0]}}and {{latLng[1]}}. I used innerHTMLinstead of outerHTMLso that only the contents of infowindow.html are inserted.

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

Plunker.

普朗克

Update2:Clicking does not work the first time. It appears that 'infowindow.html' is not loaded until a second click (I tried calling scope.$apply() a second time... didn't help). When I had the plunker working, I had inlined the contents of infowindow.html in index.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>

I was using that in addListener():

我在 addListener() 中使用了它:

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

I changed the plunker to use the inlined template.

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

回答by Ethan C

The above answers are solid, but you lose your binding on:

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

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

Do this instead:

改为这样做:

infowindow.setContent( compiled[0] );

Otherwise if you have something like <div>{{myVar}}</div>, it won't update if myVaris updated in your app.

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

回答by Luke

Have you tried the compile function? http://docs.angularjs.org/api/ng.$compile

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

I did not look into angular a lot yet, but I think this could work.

我还没有深入研究 angular,但我认为这可行。

alternatively you could try bootstrapping the stuff. but I dont believe it is the correct way... http://docs.angularjs.org/guide/bootstrap

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