angular-google-maps getting GEO location from mouse click - angularjs

I am using the library angular-google-maps from http://angular-google-maps.org/. I am able to get most everything to work. What I am currently banging my head against is to get the "click" event to work on the map to give me the GEO location of where I clicked. Currently it's not even registering that I am clicking on the map.
Here is my partial:
<google-map
center="map.center"
zoom="map.zoom"
draggable='true'
>
</google-map>
and here is the controller:
// Create Map
$scope.map = {
center: {
latitude: 40.296755,
longitude: -111.696415
},
zoom: 13,
events: {
click: function (mapModel, eventName, originalEventArgs) {
alert("hola?");
}
}
};
Any help would be fantastic!

To add the event to the map, you need to attach an associative array (object) to the events attribute of the directive:
<google-map events="$scope.events" .... ></google-map>
In Controller:
$scope.events = {"click" : function () { console.log('woo-hoo') })

Related

How can I use a $watch() function in angularjs for Google Map API click event?

I want to catch the click event that happens when you click on a marker on a google map, and then execute some code. I've tried this, but it doesn't seem to be working.
$scope.$watch('click', function(newVal, oldVal) {
alert("Marker was clicked");
});
Any ideas?
Google maps displays the map in an iframe, and you can't capture clicks like that with an iframe. I use NgMap for map displays in my angularJS app, and the HTML structure ends up looking like this:
<ng-map class='map' style="">
<marker id='{{locale.id}}' position="{{locale.position}}" ng-repeat="locale in locales" on-click="showInfoW(locale)"></marker>
<info-window id="foo-iw">
<!-- info window HTML stuff here -->
</info-window>
</ng-map>
See that on-click in there? That is where you can get the click and do something in your code.
My JS looks something like this:
$scope.showInfoW = function(e, locale) {
$scope.vm.locale = locale
$scope.map.showInfoWindow('foo-iw', locale.id);
}
NgMap.getMap().then(function(map) {
vm.map = map
var latlng, bounds = new google.maps.LatLngBounds();
for (var i in $scope.locales) { // your marker list here
latlng = new google.maps.LatLng($scope.locales[i].position[0], $scope.locales[i].position[1]);
bounds.extend(latlng) // your marker position, must be a LatLng instance
}
$timeout(function() {
google.maps.event.trigger(map, 'resize');
$scope.map.fitBounds(bounds);
$scope.map.setZoom(14)
}, 500)
})
Without trying to explain everything, you can see that (using the wonderful NgMap package) you can capture the click on the marker.

Leaflet issues angular woes in showing and hiding? Want to get rid of $timeout

I have a leaflet being created with L.map('mapelement') being called. The issue is that if I click a button that "hides" the leaflet map, then click the button again to show, the leaflet map does not show up. However, when I put in a setTimeout within the link function before the map gets created and set it to 2 seconds, then the map shows every time (though I have to wait 2 seconds). Is there a better alternative to using $timeout in my custom "leaflet-map" directive to show and hide?
I created a naive example of a leaflet-map directive without seeing any of your code and am toggling the display of the map through ng-show. It works without any $timeout. It's hard to diagnose where your problems are stemming from without seeing any code or knowing how you are trying to toggle the map's display.
angular.module('demo', [])
.directive('leafletMap', function() {
return {
restrict: 'E',
scope: {
mapOptions: '&'
},
template: '<div><button ng-click="toggleShow()">Toggle Map</button><div class="demo-map" ng-show="isShown"></div></div>',
link: function(scope, elem, attrs) {
// Find element to bind to map
var mapElem = elem.children().find('div')[0],
// get map options from isolate scope
mapOptions = scope.mapOptions();
// State of hide/show
scope.isShown = true;
// Create Map.
var map = L.map(mapElem, mapOptions);
// Just taken from leaflet example
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
id: 'mapbox.streets'
}).addTo(map);
// method to toggle the shown/hidden state of map
scope.toggleShow = function() {
scope.isShown = !scope.isShown;
};
// cleanup on element destroy
elem.on('$destroy', function() {
map.remove();
});
}
};
})
.controller('DemoController', function() {
this.mapOptions = {
center: [51.505, -0.09],
zoom: 13
};
});
.demo-map {
height: 500px;
}
<script src="//cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" href="//cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" />
<div ng-app="demo" ng-controller="DemoController as ctrl">
<leaflet-map map-options="ctrl.mapOptions"></leaflet-map>
</div>
Would CSS help you ?
Create one map in a visible div
visibility: visible
Create the second map in a hidden div
visibility: hidden
Position both your div in the same position
position: absolute
When you want to toggle just change the visibility of your divs
Example: http://plnkr.co/edit/voTjyMLKTxUC183nf8ML?p=preview
(Sorry it's not angular)

angularjs google maps - markers with window - infowindow not showing

Trying to get a app using angular-google-maps with:
- multiple markers via the markers directive
- a single infowindow via the window directive
I've been through the API and multiple closed issues / questions on the git-hub site but just can't get it working... :-/
jsfiddle
For simplicity, I'm declaring the markers manually (and they're displaying correctly):
$scope.markers = [
{
id: 0,
coords: {
latitude: 37.7749295,
longitude: -122.4194155
},
data: 'restaurant'
},
{
id: 1,
coords: {
latitude: 37.79,
longitude: -122.42
},
data: 'house'
},
{
id: 2,
coords: {
latitude: 37.77,
longitude: -122.41
},
data: 'hotel'
}
];
The html looks like:
<body ng-app="app">
<div class="angular-google-map-container" ng-controller="MainCtrl">
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="map.options" events="map.events" control="googlemap">
<ui-gmap-window coords="markers.coords" show="windowOptions.show" closeClick="closeClick()">
<div>Hello</div>
</ui-gmap-window>
<ui-gmap-markers models="markers" idkey="markers.id" coords="'coords'" click="'onClick'" events="markers.events" >
</ui-gmap-markers>
</ui-gmap-google-map>
</div>
</body>
I'm applying the onClick function to the markers array using this code
$scope.addMarkerClickFunction = function(markersArray){
angular.forEach(markersArray, function(value, key) {
value.onClick = function(){
$scope.onClick(value.data);
};
});
};
The marker click functions look like
$scope.windowOptions = {
show: false
};
$scope.onClick = function(data) {
$scope.windowOptions.show = !$scope.windowOptions.show;
console.log('$scope.windowOptions.show: ', $scope.windowOptions.show);
console.log('This is a ' + data);
};
$scope.closeClick = function() {
$scope.windowOptions.show = false;
};
The $scope.onClick() function seems to be working on marker click since the console outputs what is expected - and the $scope.windowOptions.show value toggles between true and false...
I'm thinking it's the way I've connected the window html to the controller arrays and functions ? Any help is appreciated.
P.S. The API documentation examples seem out of date since they don't use show in the example but rather options.visible to show and hide infowindows - but then all the issues / examples suggest using show instead ?
I know this is an old post.
However, these days I've been struggling myself trying to do this and, moreover, the jsfiddle of the accepted answer is broken and doesn't work with latest versions of angular-google-maps directive. So, I've decided to share a working plunker hoping it can help other people.
Plunker here
This version is rendering multiple markers but just one window. Only one window can be opened at the same time.
It's based on the advises of the official site FAQ Section: See How do I only open one window at a time?
html
<ui-gmap-google-map center="map.center" zoom="map.zoom">
<ui-gmap-window
show="map.window.show"
coords="map.window.model"
options="map.window.options"
closeClick="map.window.closeClick()"
templateUrl="'infowindow.tpl.html'"
templateParameter="map.window">
</ui-gmap-window>
<ui-gmap-markers
models="map.markers"
coords="'self'"
events="map.markersEvents"
options="'options'">
</ui-gmap-markers>
</ui-gmap-google-map>
js
$scope.map = {
center: {
latitude: 39.5925511,
longitude: 2.633202
},
zoom: 14,
markers: [], // Markers here
markersEvents: {
click: function(marker, eventName, model) {
$scope.map.window.model = model;
$scope.map.window.show = true;
}
},
window: {
marker: {},
show: false,
closeClick: function() {
this.show = false;
},
options: {}
}
};
Hope it helps.
Your marker's binding is incorrect in the window directive.
Basically, you need to set a marker as selected on click and bind the window to that selected marker. See the jsfiddle for a working example.
<body ng-app="app">
<div class="angular-google-map-container" ng-controller="MainCtrl">
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" options="map.options" events="map.events" control="googlemap">
<ui-gmap-window coords="MapOptions.markers.selected.coords" show="windowOptions.show" closeClick="closeClick()">
<div>Hello</div>
</ui-gmap-window>
<ui-gmap-markers models="markers" idkey="markers.id" coords="'coords'" click="'onClick'" events="markers.events" >
</ui-gmap-markers>
</ui-gmap-google-map>
</div>
http://jsfiddle.net/gqkmyjos/
I know this is old post, but I struggled with Angular Google Map, and solve issue when you open one window for markers. If you use ng-repeat and window for each one - no problems. But when you have a markers directive, and want to show only one window, then you have an issue - window places not above marker and you need change position a little. How to do it? Let me share my experience on that.
You just need to specify pixelOffset for windowoptions like that:
JS:
$scope.windowOptions = {
pixelOffset : {
height: -25,
width: 0
}
};
HTML:
<ui-gmap-window coords='selectedmarker.coords' show='true' options='windowOptions'>
#{{ selectedmarker.tagline }}
</ui-gmap-window>
That's it. Change height for your needs.
you're better setting the marker model on the scope on click something like this:
marker click callback:
$scope.onClick = function(marker) {
$scope.selectedMarker = marker.model;
}
Then use the selectedMarker in the directive:
<ui-gmap-window coords="selectedMarker" show="windowOptions.show" closeClick="closeClick()">
<div>Hello</div>
</ui-gmap-window>
simple. assumes your marker model has longitude and latitude set of cause

AngularJS Leaflet memory leak

There is a clear memory leak in my Angular app wherever I use the following leaflet directive: https://github.com/tombatossals/angular-leaflet-directive.
Note that the directive works fine, however the memory footprint continues growing as I leave and return to any view using the directive.
The directive builds off of the leaflet javascript library found here: https://github.com/Leaflet/Leaflet
I use the directive as follows:
<div ng-controller="Explore">
<div leaflet defaults="defaults" center="center" markers="markers" layers="layers"></div>
</div>
Inside my controller I extend the leaflet directive attributes to the scope:
angular.extend($scope, {
defaults: {
dragging: true,
doubleClickZoom: false,
scrollWheelZoom: false,
maxZoom: 12,
minZoom: 12
},
center: {
lat: $scope.cities[$scope.market.city][1],
lng: $scope.cities[$scope.market.city][0],
zoom: 12
},
markers: {},
layers: {
baselayers: {
google: {
name: 'Google Streets',
layerType: 'ROADMAP',
type: 'google'
}
}
}
});
I am not sure what is causing the memory leak, but I believe it may have to do with event listeners that are not removed when $destroy is called within the leaflet directive:
scope.$on('$destroy', function () {
leafletData.unresolveMap(attrs.id);
});
On destroy the function unresolveMap is called:
this.unresolveMap = function (scopeId) {
var id = leafletHelpers.obtainEffectiveMapId(maps, scopeId);
maps[id] = undefined;
};
This is as far as I got. If anyone has come across anything similar or has any ideas as to how to attack this issue further I would greatly appreciate it :)
You should try to remove completly the map by adding a map.remove() in the on $destroy handler (From leaflet API it should: "Destroys the map and clears all related event listeners").
scope.$on('$destroy', function () {
leafletData.unresolveMap(attrs.id);
map.remove();
});
Have you tried assigning an id attribute to your map? That's what the attrs.id refers to.
<leaflet id="myMap" defaults="defaults" center="center" markers="markers" layers="layers"></leaflet>

Angular-Google-Maps: How to use 'method' in the controller

When I change my app from jQuery way to Angular way,
I try to use Angular-Google-Maps.
But I can't find where is the Google Map Objects(Map, Marker, Polygon...)
and the approach to use Object 'method' (such like getMap() , getPath(), getPosition()..).
If I need to get the position of the marker which is dragged, how can i do?
just like I usually do ?
marker = new google.maps.Marker(opts);
postion = marker.getPosition();
Edit:
I found a way how to get the marker position when it was dragged'n'dropped. You can set the callback function for the marker:
<google-map center="center" zoom="zoom" control="googleMap">
<marker coords="coords" options="options" events="events">
</google-map>
Then in the controller you define the callback:
$scope.events: {
dragend: function (marker) {
$rootScope.$apply(function () {
console.log(marker.position.lat());
console.log(marker.position.lng());
});
}
}
Old Answer:
It is currently not possible:
https://github.com/nlaplante/angular-google-maps/issues/277
However, you can get the original google.maps.Map object:
Directive call:
<google-map center="center" zoom="zoom" control="googleMap"></google-map>
Angular controller:
...
$scope.center = = {
latitude: 48.13171,
longitude: 11.549554
};
$scope.zoom = 8;
$scope.googleMap = {}; // this is filled when google map is initiated
function getMapObject() {
$scope.googleMap.control.getGMap();
}
...
Actually you don't even need events, the library already binds your marker position with the scope.
Here is how I did it in Coffee Script:
Controller:
$scope.map =
center:
latitude: k
longitude: D
zoom: 16
marker:
coord:
k
D
View:
<ui-gmap-google-map center='map.center' zoom='map.zoom'>
<ui-gmap-marker
idKey="'pin'"
coords="map.marker.coord"
options="{'draggable':true}"
>
</ui-gmap-marker>
</ui-gmap-google-map>
<pre>{{map | json}}</pre>

Resources