I want to display google maps in my page for every place (lieux).In my HTML page I have the function for the google maps.
<script>
function initialize(long,lat) {
var mapCanvas = document.getElementById('map_canvas');
var mapOptions = {
center: new google.maps.LatLng(long, lat),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(mapCanvas, mapOptions)
}
google.maps.event.addDomListener(window, 'load', initialize);
document.getElementById('map_canvas').style.display='block';
</script>
And I have the button to dispaly the map.
<div class="tab-pane" id="tab_b" ng-controller="LieuController as lieu">
<div class="list-group-item" ng-repeat="lieu in lieu.lieux ">
<button onclick="initialize({{lieu.x}},{{lieu.y}})">Click me</button>
<div id="map_canvas"></div>
</div>
So is it possible to call the function with the parameters like I did or is there another way?
There are several problems with your code. Technically it's possible to mix Angular and pure javascript DOM 0 events like you are trying. However..
1. If you already tried your own code, then you should have seen the error Angular throws in this case:
Interpolations for HTML DOM event attributes are disallowed.
This effectively prevents usage Angular scope data with out-of Angular world code. There is a workaround though you can take. You can render necessary data in some attributes and then use them. For example:
<button onclick="initialize(this.getAttribute('data-x'), this.getAttribute('data-y'))"
data-x="{{l.x}}" data-y="{{l.y}}">Click me</button>
2. Event if you fix above problem you will still have to address duplicated ids issue. Since your initialize function is supposed to render a map in separate containers per ngRepeat row, each with id map_canvas. And at the same time you library onload event, which calls initialize again.
google.maps.event.addDomListener(window, 'load', initialize);
3. That being said, you should not build an app with such an unsuccessful design. You should really work on understanding main AngularJS concepts and philosophy.
In your case you should probably make use of ng-click instead of onclick, define initialize in some sort of custom service, maybe write custom directive to handle each separate map rendering in proper containers.
Related
I am trying to use the Google Maps API to display a map within an Angular site but it appears to not initialise correctly.
My html page uses bootstrap nav nav-tabs and I use an Angular controller to switch between them.
<ul class="nav navbar-nav">
<li ng-class="{ active:myCtrl.isSet('map') }">
<a href ng-click="myCtrl.setTab('map')">Show Map</a>
</li>
</ul>
With one of the tabs containing only the google map canvas element - set up using an angular directive
Module.directive('mapPage', function() {
return {
restrict: 'E',
template: '<div id="map-canvas"></div>'
};
});
Within my angular controller I set up a listener for the window 'load' event to initialise the map as follows:
google.maps.event.addDomListener(window, 'load', myCtrl.initMap);
myCtrl.initMap = function() {
var mapOptions = {
zoom: 12,
center: new google.maps.LatLng(55.937879, -3.241619),
};
myCtrl.map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(55.937879, -3.241619),
map: myCtrl.map
});
myCtrl.map.setCenter(new google.maps.LatLng(55.937879, -3.241619));
}
What I see on screen is the map element showing a grey area with the location marker not centered correctly (it's just off screen).
If I move the map-canvas div to the main section of my index.html page (rather than a sub page within the app) it loads correctly, so I know my Google API js code and html is correct. The map also shows if the page is resized.
It just doesn't work when used on a page that is not rendered immediately. I have tried searching for similar questions/answers but could not find this particular issue.
I have created a simple fiddle that demonstrates the issue.
http://jsfiddle.net/johntough/nc0u7h2c/5/
Any help appreciated!
The issue is, you are loading Map on window load whereas the container will appear on click. Google Map has behavior (never seen documented yet but I have observed it many time though) that if the container is hidden on load, it does not load map in there. I changed your "load" to "click" and its working. The only change is as below,
google.maps.event.addDomListener(window, 'click', myCtrl.initMap);
See fiddle and verify yourself. http://jsfiddle.net/anandgh/nc0u7h2c/6/
I am using the angular google maps api defined here:
https://angular-ui.github.io/angular-google-maps/#!/api
I have the following DOM structure
<ui-gmap-markers models="destinationMarkers" coords="'self'" idKey='self.idkey' >
<div ui-gmap-windows models="destinationMarkers" control="infoWindows">
<div ng-non-bindable>
<!-- {{contents}} -->
</div>
</div>
</ui-gmap-markers>
I am trying to make it so that the info window closes when any other part of the map is clicked on, or when another window is opened. The closest I have gotten is calling: scope.infoWindows.getChildWindows() which gives access to the marker objects, however calling the associated hideWindow functions appears to do nothing. Does anyone know how to do this?
I have just come across exactly the same issue and after a little messing around i have a solution (sorry if im a little late to the game)
You must set the controller property on the window like so...
<ui-gmap-window ng-if="m.response" control="googlemap" >
The 'googlemap' control must be a member of the Scope, and 'control' must be defined as an empty object on the map object like so...
$scope.googlemap = {};
$scope.map = {
zoom: 5,
center: getMapCenter(response),
options: {
// draggable: false
},
control: {}
};
Now we can attach an event to the Marker which will enable us to iterate over the list of windows and hide them like so...
markers.push({
id: i,
...
...
events: {
click: function(e){
var windows = $scope.googlemap.getChildWindows();
for (var i = 0; i < windows.length; i++){
windows[i].hideWindow()
}
}
}
});
Trying to load a simple google map within an angular-ui modal. However no luck. The data get's passed in fine, but nothing works in terms of the map... Please help.
$modalInstance.opened.then(function() {
var mapOptions = {
center: new google.maps.LatLng(34.834442, -82.3686479),
zoom: 8
};
new google.maps.Map(document.getElementById("eventMap"), mapOptions);
});
Inside the modal html:
<div class="row clearfix">
<div class="col-md-5" id="eventMap" style="display: block; height: 150px;"></div>
</div>
I tried this in the regular page HTML and worked fine...
What am I missing?
Thank you in advance!
You can use angularjs-google-maps; an AngularJS directive for Google maps that is very flexible and powerful and easy to use. I've prepared a working demo for your case:
http://plnkr.co/edit/eEtaGH?p=preview
I hope this helps.
To remove the grayness, according to https://angular-ui.github.io/angular-google-maps/#!/faq:
If rendering starts before elements are full size, google maps calculates according to the smaller size. This is most commonly the case with a hidden element (eg, ng-show). To fix this, use "ng-if" instead, as this will wait to attach to the DOM until the condition is true, which should be after everything has rendered fully.
I've modified your plunker http://plnkr.co/edit/JetUBY?p=preview to remove the grayness.
Controller:
var ModalInstanceCtrl = function ($scope, $modalInstance, lat, lng) {
$scope.render = true;
// code here
}
Template:
<map ng-if="$parent.render" center="[{{$parent.lat}}, {{$parent.lng}}]" zoom-control="true" zoom="8"> </map>
You need to trigger 'resize' event. Follow these lines:
var map = new google.maps.Map(document.getElementById("eventMap"), mapOptions);
google.maps.event.trigger(map, 'resize', function () {
// your callback content
});
I too ran Into a similar situation, where I am loading a map in an angular modal instance. I too searched many places and did't get the correct simple solution for it.
So I gone deeper and found a simple solution for this issue.
The issue is that, the map is trying to get the div from the modal before it gets loaded, and the solution is:
In your controller take a $timeout angular parameter,
function MyController($scope,$cookies,$modal,$window,roomService,$timeout) {
**** after all your model code is defined ****
$modalInstance.opened.then(function() {
function initialize() {
var latlng = new google.maps.LatLng(-34.397, 150.644);
var myOptions = {
zoom: 8,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("eventMap"),
myOptions);
}
$timeout(function() {
initialize()
}, 1000);
});
*** use the time out to make the div load and then call the map ***
}
This time out made the map to load perfectly in the modal. A simple solution.
I am new to JS, and have found the answer to a previous question, which brought up a new question, which brought me here again.
I have a Reveal Modal that contains a Google Map API. When a button is clicked, the Reveal Modal pops up, and displays the Google Map. My problem is that only a third of the map is displaying. This is because a resize trigger needs to be implemented. My question is how do I implement the google.maps.event.trigger(map, 'resize')? Where do I place this little snippet of code?
Here is my test site. Click on the Google Map button to see the problem at hand.
http://simplicitdesignanddevelopment.com/Fannie%20E%20Zurb/foundation/contact_us.html#
The Reveal Model script:
<script type="text/javascript">
$(document).ready(function() {
$('#myModal1').click(function() {
$('#myModal').reveal();
});
});
</script>
My Google Map Script:
<script type="text/javascript">
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(39.739318, -89.266507),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),
mapOptions);
}
</script>
The div which holds the Google Map:
<div id="myModal" class="reveal-modal large">
<h2>How to get here</h2>
<div id="map_canvas" style="width:600px; height:300px;"></div>
<a class="close-reveal-modal">×</a>
</div>
UPDATE 2018-05-22
With a new renderer release in version 3.32 of Maps JavaScript API the resize event is no longer a part of Map class.
The documentation states
When the map is resized, the map center is fixed
The full-screen control now preserves center.
There is no longer any need to trigger the resize event manually.
source: https://developers.google.com/maps/documentation/javascript/new-renderer
google.maps.event.trigger(map, "resize"); doesn't have any effect starting from version 3.32
There were actually a couple of problems with your source code.
The initialize() function is created, but never called
The $(document).ready should be called after jQuery us loaded
The map should be a global variable (like #Cristiano Fontes said) and not a var map
(Important) The click event is never called. You're trying to combine the two methods Reveal from Zurb provides to open a dialog (one with JS, one with only HTML). You need to use the only JS method.
You're using the wrong ID (#myModal1 is never located in the HTML).
And now: Download the solution (Please provide us with a download/JSFiddle next time, so we don't need to create this ourselves).
Hope it helped!
Just add it here
<script type="text/javascript">
$(document).ready(function() {
$('#myModal1').click(function() {
$('#myModal').reveal();
google.maps.event.trigger(map, 'resize');
});
});
</script>
BUT you need to put the map as a global variable, so lose the var here
<script type="text/javascript">
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(39.739318, -89.266507),
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
--> map = new google.maps.Map(document.getElementById("map_canvas"),
mapOptions);
}
</script>
google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
google.maps.event.trigger(map, 'resize');
});
});
Didn't found how to leave a comment for the last answer, but +1 for Cristiano Fontes help! It worked. In my case:
<script type="text/javascript">
$('div.map-box').hide();
$('li.map').mouseover(function(){
$('div.map-box').show();
google.maps.event.trigger(map, 'resize');
});
</script>
As now, google.maps.event.trigger(map, 'resize') does nothing. Like we having mat-dialog containing google map in it and there is the same problem. I`ve found some ways you can handle it:
Init map with a timeout.
Change the size of the parent container after map inits and then change it back.
But as for me, all these ways are pretty bad and I`m looking for something better.
I'd like to use a jQuery UI button as a custom control in Google Maps API (v3), but I'm having some trouble. All I get on my map is a plain old HTML push button without any jQuery styling. My guess is that when the jQuery UI button() method is called, the 'div' containing my custom control button has not yet been attached to the DOM. Here is a code snippet containing the basic implementation that I'm trying to achieve:
<!-- GOOGLE MAPS API -->
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<!-- CUSTOM JQUERY UI -->
<link type="text/css" href="../jquery-ui-1.8.14.custom/css/ui-lightness/jquery-ui-1.8.14.custom.css" rel="stylesheet" />
<script type="text/javascript" src="../jquery-ui-1.8.14.custom/js/jquery-1.6.2.js"></script>
<script type="text/javascript" src="../jquery-ui-1.8.14.custom/js/jquery-ui-1.8.14.custom.min.js"></script>
<script>
$(document).ready(function() {
var map = new google.maps.Map(document.getElementById("map_canvas"), {
center: new google.maps.LatLng(0, 0),
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var controlDiv = document.createElement('div');
var controlButton = document.createElement('button');
controlButton.innerHTML = 'Control Button';
controlDiv.appendChild(controlButton);
// Add 'div' containing button to MVCArray in desired position on map
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(controlDiv);
$('button').button();
});
</script>
In my Info Windows, I'm building jQuery Tabs after the 'domready' event has been fired. I'm wondering if there's anything similar for building custom map controls. Or is there some other trick to get this to work? Any help or suggestions would be appreciated, thanks!
Update 7/22/11
I tried fooling around with the MVCArray 'insert_at' event by modifying the lines of code from above:
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(controlDiv);
$('button').button();
to the following:
google.maps.event.addListener(map.controls[google.maps.ControlPosition.RIGHT_BOTTOM], 'insert_at', function() {
$('button').button();
});
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].insertAt(map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].length, controlDiv);
This method is a bit more clumsy, but it seemed like a way to delay calling the jQuery button() method until after the the button element has been inserted into the map and attached to the DOM. Unfortunately, no luck. Still doesn't work. Probably some straightforward solution I'm missing!
Documentation for the insertAt() method and 'insert_at' event of the MVCArray class can be found here: http://code.google.com/apis/maps/documentation/javascript/reference.html#MVCArray