<!DOCTYPE html>
<html ng-app="locationApp">

  <head>
    <link rel="stylesheet" href="place-autocomplete.css" />
    <link rel="stylesheet" href="//rawgit.com/angular/bower-material/master/angular-material.css" />
    
    <script data-require="angular.js@1.4.8" data-semver="1.4.8" src="https://code.angularjs.org/1.4.8/angular.js"></script>
    <script data-require="angular-route.js@1.4.8" data-semver="1.4.8" src="https://code.angularjs.org/1.4.8/angular-route.js"></script>
    <script data-require="angular-aria@1.4.0" data-semver="1.4.0" src="https://code.angularjs.org/1.4.0/angular-aria.js"></script>
    <script data-require="angular-animate@1.4.8" data-semver="1.4.8" src="https://code.angularjs.org/1.4.8/angular-animate.js"></script>
    <script src="//rawgit.com/angular/bower-material/master/angular-material.js"></script>
    <script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
    <script src="app.js"></script>
    <script src="home-ctrl.js"></script>
    <script src="place-autocomplete.js"></script>
  </head>

  <body>
    <ng-view></ng-view>
  </body>

</html>
'use strict';

/**
 * @ngdoc directive
 * @name locationApp.directive:placeAutocomplete
 * @description
 *
 * # An element directive that provides a dropdown of
 * location suggestions based on the search string.
 * When an item is selected, the location's latitude
 * and longitude are determined.
 * 
 * This directive depends on the Google Maps API
 * with the places library
 * 
 * <script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
 * 
 * Usage:
 * <place-autocomplete ng-model="selectedLocation"></place-autocomplete>
 *
 * Credit:
 * http://stackoverflow.com/a/31510437/293847
 */
angular.module('locationApp')
  .directive('placeAutocomplete', function() {
    return {
      templateUrl: 'place-autocomplete.html',
      restrict: 'E',
      replace: true,
      scope: {
        'ngModel': '='
      },
      controller: function($scope, $q) {
        if (!google || !google.maps) {
          throw new Error('Google Maps JS library is not loaded!');
        } else if (!google.maps.places) {
          throw new Error('Google Maps JS library does not have the Places module');
        }
        var autocompleteService = new google.maps.places.AutocompleteService();
        var map = new google.maps.Map(document.createElement('div'));
        var placeService = new google.maps.places.PlacesService(map);
        $scope.ngModel = {};

        /**
         * @ngdoc function
         * @name getResults
         * @description
         *
         * Helper function that accepts an input string
         * and fetches the relevant location suggestions
         *
         * This wraps the Google Places Autocomplete Api
         * in a promise.
         *
         * Refer: https://developers.google.com/maps/documentation/javascript/places-autocomplete#place_autocomplete_service
         */
        var getResults = function(address) {
          var deferred = $q.defer();
          autocompleteService.getQueryPredictions({
            input: address
          }, function(data) {
            deferred.resolve(data);
          });
          return deferred.promise;
        };

        /**
         * @ngdoc function
         * @name getDetails
         * @description
         * Helper function that accepts a place and fetches
         * more information about the place. This is necessary
         * to determine the latitude and longitude of the place.
         *
         * This wraps the Google Places Details Api in a promise.
         *
         * Refer: https://developers.google.com/maps/documentation/javascript/places#place_details_requests
         */
        var getDetails = function(place) {
          var deferred = $q.defer();
          placeService.getDetails({
            'placeId': place.place_id
          }, function(details) {
            deferred.resolve(details);
          });
          return deferred.promise;
        };

        $scope.search = function(input) {
          if (!input) {
            return;
          }
          return getResults(input).then(function(places) {
            return places;
          });
        };
        /**
         * @ngdoc function
         * @name getLatLng
         * @description
         * Updates the scope ngModel variable with details of the selected place.
         * The latitude, longitude and name of the place are made available.
         *
         * This function is called every time a location is selected from among
         * the suggestions.
         */
        $scope.getLatLng = function(place) {
          if (!place) {
            $scope.ngModel = {};
            return;
          }
          getDetails(place).then(function(details) {
            $scope.ngModel = {
              'name': place.description,
              'latitude': details.geometry.location.lat(),
              'longitude': details.geometry.location.lng(),
            };
          });
        }
      }
    };
  });
angular.module('locationApp', ['ngAnimate','ngMaterial', 'ngRoute'])
.config(function($routeProvider) {
  $routeProvider.
      when('/home', {
        templateUrl: 'home.html',
        controller: 'HomeCtrl'
      }).
      otherwise({
        redirectTo: '/home'
      });
});
<md-content>
  <md-toolbar>
    <div class="md-toolbar-tools">
      <h2>
          <span>Google places/location suggestions with md-autocomplete</span>
        </h2>
      <span flex></span>
    </div>
  </md-toolbar>
</md-content>
<md-content layout-padding>
  <p>Start typing the name of a place/location below</p>
  <div class="md-padding">
    <place-autocomplete ng-model="location"></place-autocomplete>
    <div ng-if="location.name">
      <h4>Selected location</h4>
      <pre>{{location|json}}</pre>
    </div>
  </div>
</md-content>
angular.module('locationApp')
.controller('HomeCtrl', function($scope) {
  
});
<div id="place-autocomplete">
  <md-autocomplete md-no-cache="false" md-selected-item="location" md-selected-item-change="getLatLng(item)" ng-model-options="{debounce: 600}" md-search-text-change="search(searchText)" md-search-text="searchText" md-items="item in search(searchText)" md-item-text="item.description" md-min-length="2" md-max-length="50" md-floating-label="Location (place, city or region)">
    <md-item-template>
      <span md-highlight-text="searchText" md-highlight-flags="^i">{{item.description}}</span>
    </md-item-template>
    <md-not-found>
      No matches found for "{{searchText.description}}".
    </md-not-found>
  </md-autocomplete>
</div>
/*
Optional adjustments for md-autocomplete in mobile screens
*/

#place-autocomplete > md-autocomplete md-input-container {
  margin-top: -10px;
}


/*Media query for tablets and above */

@media screen and (min-width: 480px) {
  #place-autocomplete > md-autocomplete md-input-container {
    padding-bottom: 0;
  }
}