Monday, May 20, 2024
14
rated 0 times [  20] [ 6]  / answers: 1 / hits: 17796  / 12 Years ago, wed, january 9, 2013, 12:00:00

I'm trying to include a template file views/infowindow.html as the content of my InfoWindow from service I wrote to initiate the 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 content when 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>).



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



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 should be doing). I would prefer to load the template on the event instead of caching and injecting it for each marker.



EDIT Looking at $templateCache and a related SO question.



EDIT 2 Here's a plunk that tries to use $compile (the content of InfoWindow is still <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.



Moving the $compile outside and then passing the compiled template into .addListener solves this problem:



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.


More From » google-maps-api-3

 Answers
43

After you add the content to 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).



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



Without more code, it is difficult to give a more precise answer. However, here is a similar question and answer you 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 content against 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.latLng because the ng-included template needs to interpolate {{latLng[0]}} and {{latLng[1]}}. I used innerHTML instead of outerHTML so that only the contents of infowindow.html are inserted.



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:



<script type=text/ng-template id=/test.html>
<h4>{{latLng[0]}},{{latLng[1]}}</h4>
</script>


I was using that in addListener():



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


I changed the plunker to use the inlined template.


[#80995] Tuesday, January 8, 2013, 12 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
estefanib

Total Points: 508
Total Questions: 104
Total Answers: 83

Location: Lebanon
Member since Sun, Aug 2, 2020
4 Years ago
;