web-dev-qa-db-ja.com

AngularJS ng-Google Maps InfoWindow内に含めますか?

グーグルマップAPIを開始するために書いたサービスからのインフォウィンドウのコンテンツとしてテンプレートファイルviews/infowindow.htmlを含めようとしています:

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

ただし、InfoWindowに挿入されたときにAngularはcontentを処理していないようです(Dev Toolsを介してコードを検査する場合、挿入されるコードは<div ng-include src="'views/infowindow.html'"></div>です)。

Angularがインフォウィンドウに挿入される前にインクルードを前処理することを望んでいましたが、残念ながら違います。

私がやろうとしていることは可能ですか?

テンプレートをinfowindow.setContent()に渡す前に、なんらかの方法でキャッシュする必要があると思いますが、その方法がわかりません(または、それが私であるかどうかもわかりません)。すべきしている)。マーカーごとにテンプレートをキャッシュして挿入するのではなく、イベントにテンプレートをロードしたいと思います。

[〜#〜] edit [〜#〜]$ templateCacheと 関連SO質問

EDIT 2これが$compileを使おうとする plunk です(InfoWindowの内容はまだ<div id="infowindow_content" ng-include src="'infowindow.html'"></div>です)


解決

これの根拠は 以下のマークの答え から来ました。彼のソリューションでは、InfoWindowのコンテンツは(任意のマーカーの)最初のクリックでコンパイルされますが、おそらくGoogleMapsが待ち遠しいため、InfoWindowはマーカーをもう一度クリックするまで実際には開きません。

$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

更新されたプランカー

14
jacob

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 )

$ compiledできるのはDOM要素だけだという印象を受けました。つまり、最初にコンテンツをDOMに追加してから、コンパイルする必要がありました。それは真実ではないことが判明しました。上記では、最初にcontentscopeに対してコンパイルしてから、それをDOMに追加します。 (これがデータバインディングを壊す可能性があるかどうかはわかりません。つまり、$ compileによって設定された$ watch()esです。)ngに含まれるテンプレートはscope.latLng{{latLng[0]}}を補間する必要があるため、{{latLng[1]}}を設定する必要がありました。 infowindow.htmlのコンテンツのみが挿入されるように、innerHTMLの代わりにouterHTMLを使用しました。

プランカー

Update2:初回クリックは機能しません。 'infowindow.html'は2回クリックするまでロードされないようです(scope。$ apply()をもう一度呼び出してみました...役に立ちませんでした)。プランカーを機能させたとき、infowindow.htmlの内容をindex.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>';

インラインテンプレートを使用するようにプランカーを変更しました。

13
Mark Rajcok

コンパイル機能を試しましたか? http://docs.angularjs.org/api/ng.$compile

angularはまだあまり調べていませんが、これでうまくいくと思います。

あるいは、ブートストラップを試すこともできます。しかし、それが正しい方法だとは思いません... http://docs.angularjs.org/guide/bootstrap

1
Luke