Last active
July 20, 2017 08:35
-
-
Save KeithNdhlovu/d1d9021a2c7f90ff25b30f4187051491 to your computer and use it in GitHub Desktop.
Angular JS Directives for Google map with place picker and on pin drag callback update position and Geocode address from location
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- [ You obviously need google maps] --> | |
<script type="text/javascript" src='https://maps.google.com/maps/api/js?key=[ "The secret key here" ]&libraries=places'></script> | |
<style> | |
/* Always set the map height explicitly to define the size of the div | |
* element that contains the map. */ | |
#gmaps { | |
width: 100%; | |
height: 200px; | |
} | |
</style> | |
..... | |
<!-- How to use the place picker --> | |
<input id="address" | |
name="address" | |
type="text" | |
class="validate" | |
googleplace | |
on-place-changed="onPlaceChanged(placeDetails)" | |
class="validate"> | |
..... | |
<!-- How to use the google map --> | |
<div googlemap ng-model="addressDetails"></div> | |
..... | |
<!-- The inputs for the position --> | |
<input id="latitude" | |
name="latitude" | |
ng-model="latitude" | |
ng-model-options="{ updateOn: 'blur' }" | |
ng-change="reverseGeoCode(latitude, longitude)" | |
type="text"> | |
<input id="longitude" | |
name="longitude" | |
ng-model="longitude" | |
ng-model-options="{ updateOn: 'blur' }" | |
ng-change="reverseGeoCode(latitude, longitude)" | |
type="text"> | |
..... | |
<script> | |
var app = angular.module('app', ['kevin.googlemap', 'kevin.googleplace']); | |
app.controller('sampeController', [$scope, function('scope') { | |
// Set the place details | |
$scope.addressDetails = { | |
lat: 200.22, | |
long: 200.00, | |
address: 'Some Awesome place' | |
}; | |
// Since we also want to know what the address is if i just change the lat, long ... we need to listed for changes | |
// What to do when the place updates | |
$scope.onPlaceChanged = function(placeDetails) { | |
// console.log(placeDetails); | |
// udpate the address input and the lat / long inputs with new data | |
$scope.latitude = placeDetails.lat; | |
$scope.longitude = placeDetails.long; | |
$scope.address = placeDetails.address; | |
$scope.$broadcast('onPlaceChanged', placeDetails); | |
}; | |
// We need to ask for geocoder to give us an address when the lat longs have been updated | |
$scope.reverseGeoCode = function(latitude, longitude) { | |
var position = { | |
lat: parseFloat(latitude), | |
long: parseFloat(longitude) | |
}; | |
$scope.$broadcast('reverseGeo', position); | |
}; | |
}]; | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
angular.module('kevin.googlemap', []) | |
.directive('googlemap', function() { | |
// directive link function | |
var link = function(scope, element, attrs) { | |
var map, infoWindow; | |
var markers = []; | |
var geocoder = new google.maps.Geocoder; | |
// map config | |
var mapOptions = { | |
center: new google.maps.LatLng(scope.ngModel.lat, scope.ngModel.long), | |
zoom: 15, | |
mapTypeId: google.maps.MapTypeId.ROADMAP, | |
scrollwheel: true | |
}; | |
// init the map | |
function initMap() { | |
if (map === void 0) { | |
map = new google.maps.Map(element[0], mapOptions); | |
} | |
} | |
// place a marker | |
function setMarker(map, position, title, content, icon) { | |
var marker; | |
var markerOptions = { | |
position: position, | |
map: map, | |
title: title, | |
icon: icon, | |
draggable:true, | |
}; | |
for (var i in markers) { | |
markers[i].setMap(null); | |
} | |
marker = new google.maps.Marker(markerOptions); | |
map.setCenter(position); | |
map.setZoom(17); | |
markers.push(marker); // add marker to array | |
google.maps.event.addListener(marker, 'dragend', function() { | |
var position = { | |
lat: parseFloat(marker.position.lat()), | |
long: parseFloat(marker.position.lng()) | |
}; | |
geocodeLatLng(geocoder, map, position); | |
}); | |
updateAddressComponents(title, position) | |
} | |
function updateAddressComponents(title, position) { | |
// udpate address | |
$("#address").val(title); | |
$("#latitude").val(position.lat()); | |
$("#longitude").val(position.lng()); | |
}; | |
function geocodeLatLng(geocoder, gMap, position) { | |
var latlng = {lat: position.lat, lng: position.long}; | |
geocoder.geocode({'location': latlng}, function(results, status) { | |
if (status === 'OK') { | |
if (results[0]) { | |
setMarker(map, new google.maps.LatLng(position.lat, position.long), results[0].formatted_address, ''); | |
} else { | |
setMarker(map, new google.maps.LatLng(position.lat, position.long), 'Unknown address', ''); | |
console.log('No results found for selected place'); | |
} | |
} else { | |
setMarker(map, new google.maps.LatLng(position.lat, position.long), 'Unknown address', ''); | |
console.warn('GEOCODE', 'No results found for selected place'); | |
console.warn('GEOCODE-STATUS', status); | |
} | |
}); | |
} | |
// We listen for changes on the input values, and then we prompt for geocode | |
scope.$on('reverseGeo', function (event, position) { | |
console.log("onReverseGeo", position); | |
geocodeLatLng(geocoder, map, position); | |
}); | |
// When the place has changed | |
scope.$on('onPlaceChanged', function (event, placeDetails) { | |
console.log("onPlaceChanged", placeDetails); | |
setMarker(map, new google.maps.LatLng(placeDetails.lat, placeDetails.long), placeDetails.address, ''); | |
}); | |
// show the map and place some markers | |
initMap(); | |
// Set the marker from the given values from the marker | |
setMarker(map, new google.maps.LatLng(scope.ngModel.lat, scope.ngModel.long), scope.ngModel.address, ''); | |
}; | |
return { | |
restrict: 'A', | |
template: '<div id="gmaps"></div>', | |
replace: true, | |
scope: { | |
ngModel: '=', | |
}, | |
link: link | |
}; | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
angular.module('kevin.goolgeplace', []) | |
.directive('googleplace', [ function() { | |
return { | |
scope: { | |
onPlaceChanged: '&' | |
}, | |
link: function(scope, element, attrs, model) { | |
var options = { | |
}; | |
scope.gPlace = new google.maps.places.Autocomplete(element[0], options); | |
google.maps.event.addListener(scope.gPlace, 'place_changed', function() { | |
var geoComponents = scope.gPlace.getPlace(); | |
var latitude = geoComponents.geometry.location.lat(); | |
var longitude = geoComponents.geometry.location.lng(); | |
var addressComponents = { | |
lat: latitude, | |
long: longitude, | |
address: geoComponents.formatted_address | |
}; | |
// Update map details | |
scope.onPlaceChanged({placeDetails: addressComponents}); | |
// Update the value of address | |
$("#address").val(addressComponents.address); | |
}); | |
} | |
}; | |
}]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment