Подтвердить что ты не робот

AngularJS ng-include внутри Google Maps InfoWindow?

Я пытаюсь включить файл шаблона views/infowindow.html в качестве содержимого моего InfoWindow из службы, которую я написал, чтобы инициировать карты google 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

Однако, кажется, что Angular не обрабатывает content, когда он вставлен в InfoWindow (при проверке кода с помощью Dev Tools вставленный код <div ng-include src="'views/infowindow.html'"></div>).

Я надеялся, что Angular будет предварительно обработать мой include до того, как он будет вставлен в InfoWindow, но, увы, нет.

Я пытаюсь сделать это?

Я думаю, что мне придется каким-то образом кэшировать шаблон, прежде чем передать его на infowindow.setContent(), но я не знаю, как это сделать (или если это даже то, что я должен делать). Я бы предпочел загружать шаблон в событие вместо кэширования и вводить его для каждого маркера.

РЕДАКТИРОВАТЬ Глядя на $templateCache и связанный вопрос SO.

EDIT 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.

4b9b3361

Ответ 1

После добавления 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 могут быть скомпилированы в $, т.е. я должен был сначала добавить контент в DOM, а затем скомпилировать его. Оказывается, это неверно. Выше, я сначала скомпилирую content против scope, а затем добавлю его в DOM. (Я не знаю, может ли это сломать привязку данных, т.е. $Watch(), которые были настроены с помощью компиляции $.) Мне пришлось установить scope.latLng, потому что шаблон, содержащий ng, должен интерполировать {{latLng[0]}} и {{latLng[1]}}. Я использовал innerHTML вместо outerHTML, чтобы вставлялось только содержимое infowindow.html.

Plunker.

Update2: Щелчок не работает в первый раз. Похоже, что "infowindow.html" не загружается до второго щелчка (я попытался вызвать область действия. $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>';

Я изменил плункер, чтобы использовать встроенный шаблон.

Ответ 2

Вышеуказанные ответы прочны, но вы теряете привязку:

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

Сделайте это вместо:

infowindow.setContent( compiled[0] );

В противном случае, если у вас есть что-то вроде <div>{{myVar}}</div>, оно не будет обновляться, если в вашем приложении будет обновлено myVar.

Ответ 3

Вы пробовали функцию компиляции? http://docs.angularjs.org/api/ng.$compile

Я еще не рассматривал angular, но думаю, что это может сработать.

В качестве альтернативы вы можете попробовать загрузочный файл. но я не верю, что это правильный путь... http://docs.angularjs.org/guide/bootstrap