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.
Ответы
Ответ 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