Google Places Api integration with IONIC and the Long Press Issue

abhay.kumar   |  19th March, 2016

Google Maps are changing the way we see the world. Lets change the way we look at Google Maps (smile)

Google Maps are a perfect match when you are dealing with location based apps. In this article we will learn to integrate the Google Maps api and Google Places api in our Ionic App and look at the solution to long press issue that Ionic suffers from and how to resolve that. 

Get Ionic running:

  • Make sure you have node.js installed on your system
  • $ sudo npm install -g cordova
  • $ sudo npm install -g ionic

Create a new Ionic Application:

ionic start googlePlacesDemo blank
cd googlePlacesDemo/

Get list of all the platforms added in your application:

ionic platform

you will see the list of all the installed platforms

Example :
Installed platforms: ios 3.8.0
Available platforms: amazon-fireos, android, blackberry10, browser, firefoxos, osx, webos

Add Android and iOS platforms to you app:

ionic platform add android
ionic platform add ios

Following plugins will be installed once any platform is added:

  • cordova-plugin-console
  • cordova-plugin-device
  • cordova-plugin-splashscreen
  • cordova-plugin-statusbar
  • cordova-plugin-whitelist
  • ionic-plugin-keyboard

ng-cordova is an AngularJs Service which integrates cordova plugins into IONIC Applications. Download ng-cordova.master.zip from here and place the ng-cordova.min.js in the www/js. ngCordova depends on AngularJS  . In your index.html , place ng-cordova.min.js before cordova.js and after AngularJs/ Ionic files.

 

<script src="lib/ngCordova/dist/ng-cordova.js"></script>
<script src="cordova.js"></script>

Inject ngCordova as an angular dependency in your angular module

angular.module('myApp', ['ngCordova'])

Test the app on the browser

ionic serve --lab

Lets add google places api in your index.html

<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places,geometry&sensor=false"></script>

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<!-- google places api -->
<script src="http://maps.googleapis.com/maps/api/js?sensor=false&amp;libraries=places"></script>
<!-- google places api ends -->
<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="js/ng-cordova.min.js"></script>
<script src="cordova.js"></script>
<!-- your app's js -->
<script src="js/app.js"></script>
</head>
<body ng-app="starter">
<ion-pane>
<ion-header-bar class="bar-stable">
<h1 class="title">Google Places Demo </h1>
</ion-header-bar>
<ion-content ng-controller="MapCtrl">
<div class="item item-input controls">
<i class="icon ion-search placeholder-icon"></i>
<input id="pac-input" type="text" placeholder="Search Location" data-tap-disabled="true" ng-model="search">
</div>
<div id="map" data-tap-disabled="true"></div>
</ion-content>
</ion-pane>
</body>
</html>

 

app.js

angular.module('starter', ['ionic'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
StatusBar.styleDefault();
}
});
})
.controller('MapCtrl', ['$scope', function($scope) {
function initialize() {
var mapOptions = {
center: { lat: 28.613939, lng: 77.209021 },
zoom: 13,
disableDefaultUI: true,// DISABLE MAP TYPE
scrollwheel: false
};
var map = new google.maps.Map(document.getElementById('map'),
mapOptions);
var input = /** @type {HTMLInputElement} */ (
document.getElementById('pac-input'));
// Create the autocomplete helper, and associate it with
// an HTML text input box.
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.bindTo('bounds', map);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
var infowindow = new google.maps.InfoWindow();
var marker = new google.maps.Marker({
map: map
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
// Get the full place details when the user selects a place from the
// list of suggestions.
google.maps.event.addListener(autocomplete, 'place_changed', function() {
infowindow.close();
var place = autocomplete.getPlace();
if (!place.geometry) {
return;
}
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17);
}
// Set the position of the marker using the place ID and location.
marker.setPlace( /** @type {!google.maps.Place} */ ({
placeId: place.place_id,
location: place.geometry.location
}));
marker.setVisible(true);
infowindow.setContent('<div><strong>' + place.name + '</strong><br>' +
'Place ID: ' + place.place_id + '<br>' +
place.formatted_address + '</div>');
infowindow.open(map, marker);
});
}
// Run the initialize function when the window has finished loading.
google.maps.event.addDomListener(window, 'load', initialize);
}])

style.css

#map {
width: 100%;
height: 100%;
}
.controls {
border: 1px solid transparent;
border-radius: 2px 0 0 2px;
box-sizing: border-box;
position: absolute;
line-height: 22px;
}
#pac-input {
background-color: #fff;
font-family: Roboto;
font-size: 15px;
font-weight: 300;
padding: 0 11px 0 13px;
text-overflow: ellipsis;
width: 90%;
margin-bottom: 0;
line-height: 15px;
font-weight: bold;
margin-left: 10%;
}
#pac-input:focus {
border-color: #4d90fe;
}
.pac-container {
font-family: Roboto;
}
#type-selector {
color: #fff;
background-color: #4d90fe;
padding: 5px 11px 0px 11px;
}
#type-selector label {
font-family: Roboto;
font-size: 13px;
font-weight: 300;
}

Now run the app on the browser:

ionic serve --lab

You will see it work as expected in the browser.

Now run the app on Android Device: 

ionic run android

Issue with Selecting Auto Complete suggestions

All Set, you might assume. There is a problem though, you will have to long press the autocomplete option to actually get it selected. The issue is that Gmap dynamically adds elements that need the data-tap-disabled property, so you'll have to manually add the property after google has added these elements to the dom.

To get it working on the Android device you need to add the following function in your controller:

$scope.disableTap = function() {
var container = document.getElementsByClassName('pac-container');
angular.element(container).attr('data-tap-disabled', 'true');
var backdrop = document.getElementsByClassName('backdrop');
angular.element(backdrop).attr('data-tap-disabled', 'true');
angular.element(container).on("click", function() {
document.getElementById('pac-input').blur();
});
};

add disableTap() function in the input type 

<input id="pac-input" type="text" placeholder="Search Location" data-tap-disabled="true" ng-change='disableTap()' ng-model="search">

Now run the App on the Android Phone. Voila!  (smile)

Initialise Google Map

 

Google Places Api

 

Place marker on Map

 

For live demo please visit this github link

 

 

    Start your Digital

    Transformation journey

    Consultancy | Design | Drupal