Estou tentando include um arquivo de modelo views/infowindow.html
como o conteúdo da minha InfoWindow do serviço que escrevi para iniciar a API do Google Maps:
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 = ''; infowindow.setContent( content ); infowindow.open( Map , marker ); }//return fn() })( marker , latLng ) );//addListener }//for
No entanto, parece que o Angular não está processando content
quando é inserido na InfoWindow (ao inspecionar o código via Dev Tools, o código que é inserido é
).
Eu esperava que o Angular pré-processasse meu include antes de ser inserido na InfoWindow, mas infelizmente não.
O que estou tentando fazer é possível?
Eu estou pensando que vou ter de alguma forma armazenar em cache o modelo antes de passá-lo para infowindow.setContent()
, mas eu não sei como fazer isso (ou se é mesmo o que eu deveria estar fazendo). Eu preferiria carregar o modelo no evento em vez de fazer o cache e injetá-lo para cada marcador.
EDIT Olhando para $ templateCache e uma questão SO relacionada .
EDIT 2 Aqui está um plunk que tenta usar $compile
(o conteúdo do InfoWindow ainda é
)
A base para isso veio da resposta de Mark abaixo . Em sua solução, o conteúdo do InfoWindow é compilado no primeiro clique (de qualquer marcador), mas a InfoWindow não abre de fato até que outro clique em qualquer marcador, provavelmente porque o GoogleMaps é impaciente.
Mover a $compile
fora e depois passar o modelo compilado para .addListener
resolve o problema:
for ( … ) { … infowindow = new google.maps.InfoWindow(); scope.markers … var content = ''; 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 atualizado .
Depois de adicionar o content
ao DOM, você precisará encontrá-lo (talvez com um seletor de jQquery?), Então $compile
() e aplicá-lo ao escopo apropriado. Isso fará com que o Angular analise seu conteúdo e atue em qualquer diretiva que ele encontrar (como ng-include).
Por exemplo, $compile(foundElement)(scope)
Sem mais código, é difícil dar uma resposta mais precisa. No entanto, aqui está uma pergunta e resposta semelhante à que você pode ver.
Atualização: ok, finalmente consegui que isso funcionasse e aprendi algumas coisas.
google.maps.event.addListener( marker, 'click', (function( marker , scope, localLatLng ){ return function(){ var content = ''; 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 )
Eu estava com a impressão de que apenas elementos DOM poderiam ser $ compilados – isto é, primeiro eu tinha que adicionar o conteúdo ao DOM, e depois compilá-lo. Acontece que isso não é verdade. Acima, primeiro compilo o content
com o scope
e, em seguida, adiciono-o ao DOM. (Eu não sei se isso pode quebrar a binding de dados – isto é, os $ watch () que foram configurados por $ compile.) Eu tive que setar scope.latLng
porque o template ng-incluído precisa interpolar {{latLng[0]}}
e {{latLng[1]}}
. Eu usei innerHTML
vez de outerHTML
para que apenas o conteúdo de infowindow.html seja inserido.
Plunker
Update2: o clique não funciona na primeira vez. Parece que ‘infowindow.html’ não é carregado até um segundo clique (tentei chamar o escopo. $ Apply () uma segunda vez … não ajudou). Quando eu tive o plunker trabalhando, eu tinha inlined o conteúdo de infowindow.html em index.html:
Eu estava usando isso em addListener ():
var content = '';
Eu mudei o plunker para usar o modelo embutido.
As respostas acima são sólidas, mas você perde sua binding:
infowindow.setContent( compiled[0].innerHTML );
Faça isso em vez disso:
infowindow.setContent( compiled[0] );
Caso contrário, se você tiver algo como
, ele não será atualizado se myVar
for atualizado no seu aplicativo.
Você já tentou a function de compilation? http://docs.angularjs.org/api/ng.$compile
Eu não olhei muito em angular ainda, mas acho que isso poderia funcionar.
Como alternativa, você pode tentar fazer o bootstrap do material. mas eu não acredito que seja a maneira correta … http://docs.angularjs.org/guide/bootstrap