Both being Google technologies, you would expect that using Google Maps with Angular would be pretty easy. While that is generally true, there is also an abundance of documentation that can actually create some confusion. One might also expect Google Maps to take a street address, but that is not the case. Google Maps requires latitude and longitude values, which you can receive using the Google Geocoding API. This post will cover the bare minimum required to get Google Maps working with Angular.
1. Install angular-google-maps
The following is a summary of the installation instructions for Angular-UI Google Maps library with some clarification.
Ideally, use Bower: bower install --save angular-google-maps
… or else you will also have to manually install lodash.js.
2. Include Scripts
Then include lodash.js and angular-google-maps.js in the <head>
of your project or view.
1 2 3 4 |
<script src='/path/to/lodash.min.js'></script> <script src='/path/to/angular-google-maps.min.js'></script> |
3. Configure Library Options
For the next step, it is not clear if including the following script is also requried:
1 2 3 |
<script src='//maps.googleapis.com/maps/api/js?sensor=false'></script> |
That depends. I don’t recommend it. Instead, adding the following config
block to your module will prevent the need to do include the script above.
1 2 3 4 5 6 7 8 9 10 11 |
angular .module('myModule', ['uiGmapgoogle-maps']) .config(function(uiGmapGoogleMapApiProvider) { uiGmapGoogleMapApiProvider.configure({ // key: 'your api key', v: '3.17', libraries: 'weather,geometry,visualization' }); }) |
Note that and API key is optional for testing. You can make up to 2500 requests per day and 5 requests per second based on your IP address. You also will most likely only need the ‘geometry’ library for basic map usage.
Also note that the above code includes the uiGmapgoogle-maps
dependency for the module
that requires it.
4. Create $scope.map
Object
Somewhere in your controller you will need a $scope.map
object. It will need to look something like this:
1 2 3 4 5 6 7 8 9 10 11 |
.controller("MapController", function($scope){ $scope.map = { center: { latitude: 45, longitude: -73 }, zoom: 8 }; }; |
You will most likely want a map marker as well, so you will need $scope.marker
. It will need to look something like this:
1 2 3 4 5 6 7 8 9 |
$scope.marker: { id: 0, coords: { latitude: 45, longitude: -73 } } |
The Google Maps directive
will specifically look for $scope.map
and $scope.marker
, so don’t be clever and rename them something else.
Since we want to supply a street address, we will have to come back and change this later. However it sets up the next step for our example so you can at least get a map on your view.
5. Google Maps Directive
In the view where you want to display your map, place the map and marker directive
s:
1 2 3 4 5 |
<ui-gmap-google-map center='map.center' zoom='map.zoom'> <ui-gmap-marker coords="marker.coords" idkey="marker.id"></ui-gmap-marker> </ui-gmap-google-map> |
6. Add Google Maps CSS
This step is actually required. You must set some sort of height to your Google Maps or else it will not be visible on the page.
1 2 3 |
.angular-google-map-container { height: 400px; } /* or whatever */ |
Note that it will NOT work if you try to set the style
attribute of the <ui-gmap-google-map>
directive. So this will not work:
1 2 3 |
<ui-gmap-google-map style="height: 400px"></ui-gmap-google-map> |
The map will still collapse and not be visible.
7. Geocode Street Address
Since we are getting an address we need to pass it to the Google Geocoding API. To do that, let’s add a factory
rather than cluttering up our controller
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
// requires $http dependency angular .module('myModule.services', []) .factory('Geocode', function($http){ // takes an address input as a string // Example: '1600 Amphitheatre Parkway Mountain View CA' var geocode = function(address){ // replace spaces with '+' address = address.replace(/ /g, '+'); return $http({ method: 'GET', // Hit the Geocode API with address, return JSON url: 'https://maps.googleapis.com/maps/api/geocode/json?address=' + address }) .then(function(res){ var lat = res.data.results[0].geometry.location.lat; var lng = res.data.results[0].geometry.location.lng; return { // format the object the way that $scope.map expects it map: { center: { latitude: lat, longitude: lng }, zoom: 16 }, // format the object the way that $scope.marker expects it marker: { id: 0, coords: { latitude: lat, longitude: lng } } }; }); }; // make this function available when factory is included as dependency return { geocode: geocode }; }) |
8. Update the controller
Now that our factory
allows us to return properly formatted $scope.map
object, we are going to change our controller
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
angular .module('myModule', ['uiGmapgoogle-maps']); .config(function(uiGmapGoogleMapApiProvider) { uiGmapGoogleMapApiProvider.configure({ // key: 'your api key', v: '3.17', libraries: 'weather,geometry,visualization' }); }) // Include Geocode factory as dependency .controller("MapController", function ($scope, Geocode) { // replace previous hardcoded $scope.map $scope.map = {}; $scope.marker = {}; // The 'address' parameter for geocode is up to you // It depends on how you want to pass in the address // i.e. user form, passing in from a view or model, etc. Geocode.geocode(address) .then(function(data){ // Once promise returns geocoded data, // $scope.map will update and display the map on the view $scope.map = data.map; $scope.marker = data.marker; }); }) |