Creating an Advanced Google Maps Component in Ionic 2



·

We all know how useful maps can be in a mobile application, and Google Maps is a great option to do just that. Of course, you can use the native Google Maps SDK through the use of a Cordova plugin, but I’m a fan of using the Google Maps JavaScript SDK.

I’ve already covered how to do a basic Google Maps implementation in Ionic 2, but when using the JavaScript SDK it’s important to consider:

What if the user does not have an Internet connection?

It’s not unreasonable to make the maps unavailable if the user does not have an Internet connection, but how do we handle that gracefully? We don’t want an error occurring and breaking the application (because the Google Maps SDK hasn’t been loaded) or otherwise causing the maps not to work, so we need to consider the following:

  • What if the user does not have an Internet connection?
  • What if the user doesn’t have an Internet connection initially but does later?
  • What if the user does have an Internet connection initially but doesn’t later?

To handle all of these scenarios, the solution we want to implement will:

  • Wait until a connection is available before loading the Google Maps SDK, rather than straight away
  • If the connection becomes unavailable, disable the Google Maps functionality
  • If the connection becomes available again, enable the Google Maps functionality again

I rely on this functionality a lot and have already implemented it in Ionic 1 and Sencha Touch, so now I’m going to cover how to set up the same functionality in Ionic 2.

Before We Get Started

Before you go through this tutorial, you should have at least a basic understanding of Ionic 2 concepts and the differences to Ionic 1. You must also already have Ionic 2 installed on your machine.

If you’re not familiar with Ionic 2 already, I’d recommend reading my Ionic 2 Beginners Guide first to get up and running and understand the basic concepts.

1. Generating a New Project

Let’s start off by simply generating a new Ionic 2 project by running the following command:

ionic start ionic2-advanced-maps blank --v2

We will eventually be making use of a provider for this application called ConnectivityService. This will handle detecting whether or not a user has an Internet connection available. We will go through the implementation later, for now we will just generate it.

Run the following command to generate the provider:

ionic g provider ConnectivityService

In order to use this provider throughout the application we will need to add it to the app.module.ts file.

Modify src/app/app.module.ts to reflect the following:

import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { ConnectivityService } from '../providers/connectivity-service';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [ConnectivityService]
})
export class AppModule {}

2. Create the Google Maps Page

First, we are going to work on the home page which we will use to hold our Google Map. We will get a basic implementation of the class set up first, and then build on it.

Modify home.ts to reflect the following:

import { Component, ElementRef, ViewChild } from '@angular/core';
import { NavController } from 'ionic-angular';
import { ConnectivityService } from '../../providers/connectivity-service';
import { Geolocation } from 'ionic-native';

declare var google;

@Component({
  selector: 'home-page',
  templateUrl: 'home.html'
})
export class HomePage {

  @ViewChild('map') mapElement: ElementRef;

  map: any;
  mapInitialised: boolean = false;
  apiKey: any;

  constructor(public navCtrl: NavController, public connectivityService: ConnectivityService) {
    this.loadGoogleMaps();
  }
}

We’ve set up a few member variables here which we will make use of later, the only one you need to specifically worry about is the apiKey. This can be omitted, but if you have an API key for Google Maps (which you will need if your app will have a high load) then you can add it here.

You will notice that at the end of the constructor we are making a call to loadGoogleMaps. This is what will trigger all of our logic but before we move onto that, we also need to create our connectivity service that is also referenced in the constructor.

We are also importing Geolocation from the Ionic Native library that we will make use of soon, and we are using ViewChild and ElementRef to set up a reference to the map element that we will add to our template later. This way, we can simply add #map to the element in the HTML, and we will be able to set up a reference to it called mapElement by doing this:

@ViewChild('map') mapElement: ElementRef;

We’ve also added declare var google; so that TypeScript won’t throw up any errors when we start using the google object (you could also install the typings for the object if you prefer).

3. Creating a Connectivity Service in Ionic 2

We’re going to make this service work both through the browser and when it is running on a device. We can much more accurately detect if the user has an Internet connection on a device if we use the Cordova Network Information plugin, so let’s add that by running the following command:

ionic plugin add cordova-plugin-network-information

We’ll also be making use of the Geolocation API, so feel free to add that plugin as well:

ionic plugin add cordova-plugin-geolocation

If you take a look at src/providers/connectivity-service.ts now it should look like this:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class ConnectivityService {

  constructor(public http: Http) {
    console.log('Hello ConnectivityService Provider');
  }

}

This is what is automatically generated by the Ionic CLI, which is a nice starting point, but we are going to have to build on that.

Modify src/providers/connectivity-service.ts to reflect the following:

import { Injectable } from '@angular/core';
import { Network } from 'ionic-native';
import { Platform } from 'ionic-angular';

declare var Connection;

@Injectable()
export class ConnectivityService {

  onDevice: boolean;

  constructor(public platform: Platform){
    this.onDevice = this.platform.is('cordova');
  }

  isOnline(): boolean {
    if(this.onDevice && Network.connection){
      return Network.connection !== Connection.NONE;
    } else {
      return navigator.onLine; 
    }
  }

  isOffline(): boolean {
    if(this.onDevice && Network.connection){
      return Network.connection === Connection.NONE;
    } else {
      return !navigator.onLine;   
    }
  }
}

We are injecting the Platform service which is provided by Ionic to detect whether we are running on iOS or Android (or neither). We want to use the network information plugin to check if the user is online if we are running on a device, so we need to run some different code if they are running through a normal browser.

We’ve simply added two functions to this service which we will be able to call later, one to check if the user isOnline and one to check if the user isOffline. These both really do the same thing, and you could get away with having just the one function if you wanted. If we are running on a device we check the online status by checking navigator.connection.type, and if we are running through a browser we instead check navigator.onLine.

Now all we need to do is import this connectivity service into any class that we want to use it in (like we have already done in home.ts).

4. Load Google Maps only when Online

Ok now that we’ve got our connectivity service sorted we can get back to the logic of our Google Maps page. There’s actually quite a few steps we need to take care of, so I’m going to do a bit of a code dump here and then walk through it.

Modify src/pages/home/home.ts to reflect the following:

import { Component, ElementRef, ViewChild } from '@angular/core';
import { NavController } from 'ionic-angular';
import { ConnectivityService } from '../../providers/connectivity-service';
import { Geolocation } from 'ionic-native';

declare var google;

@Component({
  selector: 'home-page',
  templateUrl: 'home.html'
})
export class HomePage {

  @ViewChild('map') mapElement: ElementRef;

  map: any;
  mapInitialised: boolean = false;
  apiKey: any;

  constructor(public nav: NavController, public connectivityService: ConnectivityService) {
    this.loadGoogleMaps();
  }

  loadGoogleMaps(){

    this.addConnectivityListeners();

  if(typeof google == "undefined" || typeof google.maps == "undefined"){

    console.log("Google maps JavaScript needs to be loaded.");
    this.disableMap();

    if(this.connectivityService.isOnline()){
      console.log("online, loading map");

      //Load the SDK
      window['mapInit'] = () => {
        this.initMap();
        this.enableMap();
      }

      let script = document.createElement("script");
      script.id = "googleMaps";

      if(this.apiKey){
        script.src = 'http://maps.google.com/maps/api/js?key=' + this.apiKey + '&callback=mapInit';
      } else {
        script.src = 'http://maps.google.com/maps/api/js?callback=mapInit';       
      }

      document.body.appendChild(script);  

    } 
  }
  else {

    if(this.connectivityService.isOnline()){
      console.log("showing map");
      this.initMap();
      this.enableMap();
    }
    else {
      console.log("disabling map");
      this.disableMap();
    }

  }

  }

  initMap(){

    this.mapInitialised = true;

    Geolocation.getCurrentPosition().then((position) => {

      let latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

      let mapOptions = {
        center: latLng,
        zoom: 15,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      }

      this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);

    });

  }

  disableMap(){
    console.log("disable map");
  }

  enableMap(){
    console.log("enable map");
  }

  addConnectivityListeners(){

    let onOnline = () => {

      setTimeout(() => {
        if(typeof google == "undefined" || typeof google.maps == "undefined"){

          this.loadGoogleMaps();

        } else {

          if(!this.mapInitialised){
            this.initMap();
          }

          this.enableMap();
        }
      }, 2000);

    };

    let onOffline = () => {
      this.disableMap();
    };

    document.addEventListener('online', onOnline, false);
    document.addEventListener('offline', onOffline, false);

  }

}

As I mentioned before, the first thing we do is call the loadGoogleMaps function that we have now created. This first checks if the google object is available, which would mean the SDK has already been loaded. If the SDK has not been loaded then we check if the user is online and then we load it by injecting the script into the document. Notice that we also supply a callback function that will trigger when the SDK has been loaded, this way we know when it is safe to start doing stuff with the map. At this point, if there is no Internet connection then we don’t do anything.

The next thing we do (assuming an Internet connection is available) is run the initMap function. This simply handles creating a new map by using the loaded Google Maps SDK and sets the coordinates to the users current location using the Geolocation API.

The only other important bit of code here is the addConnectivityListeners function. This will constantly listen for when the user comes back online, and when they do it will trigger the whole loading process we just discussed above (if it has not been completed already).

This code will also call the enableMap and disableMap functions every time the Internet connection is lost or gained. Right now these don’t do anything apart from log a message to the console, but you can modify these to take whatever action you need.

5. Add the Map to the Template

If you’ve tried running your code during this process you will have found that no map actually displays on the screen (and you’ll probably get some errors too). This is because we still need to add the map to our template and also add a bit of styling.

Modify src/pages/home/home.html to reflect the following:

<ion-header>
  <ion-navbar>
    <ion-title>Map</ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
  <div #map id="map"></div>  
</ion-content>

Modify map.scss to reflect the following:

.ios, .md {

  home-page {

    .scroll-content {
      height: 100%
    }

    #map {
      width: 100%;
      height: 100%;
    }

  }

}

Summary

If you compare the code of this tutorial to my other Google Maps tutorial for Ionic 2 you’ll notice that it is a lot more complex. You can’t assume that the use will always have an Internet connection though, so it means a solution like this is necessary in a production environment. If you were to go with the simpler approach and your user didn’t have an Internet connection when they first opened the app then it just wouldn’t work at all until they completely restart the app.

The good news is though that this process never really changes, now that you’ve created one map component you should be able to quite easily drop it into any of your applications and just build on top of it.

If you’d like to see how to do some more things with Google Maps in Ionic 2, my other tutorial covers how to add markers and info windows to the map.

What to watch next...

  • Евгений Опрышко

    $ ionic plugin add plugin add cordova-plugin-geolocation

    Will produce an error like following:
    Fetching plugin “plugin” via npm
    Error: Cannot find plugin.xml for plugin ‘package’. Please try adding it again.

    It seems you mistyped, command should look like this:
    $ ionic plugin add cordova-plugin-geolocation

    • Thanks for pointing that out, all fixed now

  • Cris

    Importing Page and/or NavController and/or Platform from ‘ionic/ionic’ doesn’t work, it works importinf from ‘ionic-angular’

  • Zaid Ibnu Awwal

    Hi Josh…
    In Chrome Console Im getting this:
    Uncaught Error: Cannot find module “../../providers/connectivity-service/connectivity-ser…
    What Happen,

    Iv’e already add this

    import {ConnectivityService} from ‘./providers/connectivity-service/connectivity-service’;
    and

    import {FromPage} from ‘./pages/book-from/book-from’;
    import {ConnectivityService} from ‘./providers/connectivity-service/connectivity-service’;

    did i missed something…

  • Victor Carvalho

    I don’t understand what those lines do:
    document.addEventListener(‘online’, onOnline, false);
    document.addEventListener(‘offline’, onOffline, false);

    In my case, I just want to make a “console.log(“Is offline”)” to show “automatically” when my network status is offline…

    • Sure, so you could do:

      document.addEventListener(‘offline’, () => {
      console.log(“offline”);
      }, false);

      and every time the device switches to the offline state the console.log will be triggered. It just adds an event listener for the ‘offline’ event which fires every time the app goes offline.

      • Victor Carvalho

        Didn’t work… I need this functionality to work everywhere on my app, so I put the code on app.js…
        I created ConectivityService exactly like yours, and import on my app.ts, and in the constructor I called a method with your code:

        document.addEventListener(‘offline’, () => {
        console.log(“offline”);
        }, false);

        But I don’t understand yet how this is supposed to work… what is the ‘ofline’ of that listener?

        Thanks

      • Victor Carvalho

        I realize why don’t work here… I’m testing on chrome, and only with:

        window.addEventListener(‘online’, function(e) {
        console.log(“ONLINE CHROME”);
        }, false);

        worked…(I can’t test on Mozilla right now…)

  • Hi Josh. I’ve been trying to make this work with the latest ionic version 2.0.0-beta.22 (as of March 26 2016)

    Getting following error:

    Cannot resolve all parameters for ‘ConnectivityService'(?).

    The constructor argument for the provider has changed somewhat. I tried both

    constructor(@Inject(Platform) platform)

    constructor(platform)

    but the same error always eventuates… and I’m just getting a blank page

    Do you have any ideas as to why this may be?

    • Hey Dirk, I’ve just updated the code above for the latest version. The @Inject syntax isn’t used anymore, but you’ll have to make sure to use static get parameters() in its place. I’ve just gone through and done a quick update of the code, I haven’t actually tested it so let me know if there’s still issues.

      • You’re the man Josh – works perfectly now. Adding that static get block is all that was needed. Your tutorials help me a great deal with my current project. Thanks neighbour (from a Hobartian 🙂

      • arsene

        hello! can you help me??? i try the same code but it doesn’t work

  • Matthew Catellier

    This may be a silly question. but does it work for .ts files too? My teacher showed my me a demo in class that all use .ts files. Is there a reason to use .ts over .js? will this apporach work for both?

  • Miles Holt

    Great tutorial thanks. Just got one error – ‘apiKey is not defined’. Corrected this line to get it working – ‘script.src = ‘http://maps.google.com/maps/api/js?key=’ + this.apiKey + ‘&callback=mapInit’;’

    • arsene

      did you find solution?

  • Maximiliano Morales

    Hi Josh thanks for the tutorial. I attempt to do it with the tabs template but the map never appears and no error in the console. The code here works perfect with single pages I didn’t try with sidemenu. If you or anyone have any idea of what’s i’m missing it would be appreciated.

  • Alejandro Planter

    Hi Josh, just one NOOB question, if i want to move all this map thing instead of home app.js to a folder inside (app/pages/map/) instead like yours (app/), how should I route it?

  • Alejandro Planter

    I just don’t know what else to do, the code is perfect, but I’m still getting this from CLI:

    Error: Cannot find module ‘angular2/core’ from ‘/Users/alejandroplanter/Desktop/APPDEV/ComiendoMazatlan/app/providers/connectivity-service’

    Any help?

    • In the latest version you will need to change any ‘angular2’ imports to be ‘@angular’ instead.

      • Alejandro Planter

        It worked, but now i only see white screen.

  • Zana Y.

    Hi everybody, nice work…! thanks man, I have a question….. hot to implement it a tabs because i have attempted to do it with the tabs template but the map never appears and nothin is wrong in console…! I have used in single page and it does work perfectly but in the same application it does not work twice (the same code) in tabs…. please could you help me? i am stuck now … help!

    • arsene

      can you help me? it doesn’t work here

  • arsene

    i get a error , something like this with the last ionic v2
    zone.js:234 Uncaught TypeError: Cannot read property ‘offsetWidth’ of null_.Sf @ js?key=AIzaSyCFuotgzsCX18-4hORZXndoZ4_PL_LkOSc&callback=mapInit:81Bg @ js?key=AIzaSyCFuotgzsCX18-4hORZXndoZ4_PL_LkOSc&callback=mapInit:89(anonymous function) @ dentiste-detail-map.js:99ZoneDelegate.invoke @ zone.js:323Zone.runGuarded @ zone.js:230(anonymous function) @ zone.js:206

    Failed to parse SourceMap: http://localhost:8100/build/js/app.bundle.js.map. i need a help

  • Pingback: Ionic 2: How to Use Google Maps & Geolocation | HTML5 Mobile Tutorials | Ionic, Phaser, Sencha Touch & PhoneGap()

  • willmillingtonevans

    Hi Josh,

    Really helpful post and thorough solution.
    However I noticed that you referred to your connectivity service as “connectivityService” in your constructor but in the rest of the code you used “connectivity”.
    Otherwise it works perfectly!

  • Саша Завалий

    I was struggling to make it work and finally I did it 😀
    here is the project
    https://github.com/alexandrzavalii/ionic2-advanced-map

    • Runfast Webmaster

      Hi, on iOS I have a blank map. Just the title and the map seems not loaded…

  • Ritesh Bhat

    getting all these errors on ionic serve

    TypeScript error: C:/Users/Ritesh/Grassroot/app/pages/map/map.ts(22,15): Error TS2304: Cannot find name ‘google’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/pages/map/map.ts(22,47): Error TS2304: Cannot find name ‘google’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/pages/map/map.ts(27,17): Error TS2339: Property ‘connectivity’ does not exist on type ‘MapPage’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/pages/map/map.ts(31,20): Error TS2339: Property ‘mapInit’ does not exist on type ‘Window’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/pages/map/map.ts(51,17): Error TS2339: Property ‘connectivity’ does not exist on type ‘MapPage’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/pages/map/map.ts(71,26): Error TS2304: Cannot find name ‘google’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/pages/map/map.ts(76,22): Error TS2304: Cannot find name ‘google’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/pages/map/map.ts(79,24): Error TS2304: Cannot find name ‘google’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/pages/map/map.ts(100,23): Error TS2304: Cannot find name ‘google’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/pages/map/map.ts(100,55): Error TS2304: Cannot find name ‘google’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/providers/connectivity-service/connectivity-service.ts(14,35): Error TS2339: Property ‘connection’ does not exist on type ‘Navigator’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/providers/connectivity-service/connectivity-service.ts(16,36): Error TS2339: Property ‘connection’ does not exist on type ‘Navigator’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/providers/connectivity-service/connectivity-service.ts(18,31): Error TS2304: Cannot find name ‘Connection’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/providers/connectivity-service/connectivity-service.ts(26,35): Error TS2339: Property ‘connection’ does not exist on type ‘Navigator’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/providers/connectivity-service/connectivity-service.ts(28,36): Error TS2339: Property ‘connection’ does not exist on type ‘Navigator’.
    TypeScript error: C:/Users/Ritesh/Grassroot/app/providers/connectivity-service/connectivity-service.ts(30,31): Error TS2304: Cannot find name ‘Connection’.

  • Kelvin Forteta

    Hello Josh, I have implemented everything in this tutorial but my typescript file refused to compile because of this line of code this.map = new google.maps.Map(document.getElementById(“map”), mapOptions); the error message it’s showing is: TypeScript error: W:/MobileApps/ionic2-advanced-maps/app/pages/map/map.ts(100,51): Error TS2304: Cannot find name ‘google’., please do you have any what i am to do so it can find that google name it’s looking for? please reply

    • Cyril Ade

      Hey Kevin, try running this command in your project folder thus:
      cd ionic2-advanced-maps
      typings install dt~google.maps –global

      should resolve your error

      • levantam

        How? it it does not work

  • Cyril Ade

    Hello Josh, first of all i would like to thank you for the tutorial its been really helpful through my leaning process,
    i’m using the Ionic CLI Version: 2.0.0-beta.32 and Ionic App Lib Version: 2.0.0-beta.18 and i could not get your ionic 2 project to run successfully, i keep getting an error thus :

    Error TS2339: Property ‘connection’ does not exist on type ‘Navigator’.

    could you help clearing up this error please

    • Alan

      Hi Cyril, did you get this to work at all?

  • worldnick

    Endless pain “ParseError: ‘import’ and ‘export’ may appear only with ‘sourceType: module'”

    • worldnick

      So far using the ionic g provider connectivity-service command to install seems to have helped with the module load problem. Now I’m just dealing with a missing app.bundle.js.

      • worldnick

        It seems this “Property ‘connection’ does not exist on type ‘Navigator’.” is a fairly common problem. Perhaps the plugin needs a typescript definition?

      • Yes, to brute force your way past type warnings you can just do something like ‘declare var navigator;’ above the the @Component decorator. Using the navigator[‘connection’] syntax rather than navigator.connection may also help.

      • worldnick

        I can do ‘declare var navigator;’ and ‘declare var Connection;’ to get the build to happen but then I get this error:

        “EXCEPTION: Error: Uncaught (in promise): EXCEPTION: Error in :0:0
        ORIGINAL EXCEPTION: No provider for ConnectivityService!
        ORIGINAL STACKTRACE:”

        I think I’m just going to have to start a new project with the –ts flag and try that even though that seems really weird since ionic2 is all typescript so why wouldn’t you want that flag?

      • The –ts flag is no longer needed, this tutorial was written for an older version, including the –ts flag has no effect now. The error suggests that you haven’t added the ConnectivityService to the ionicBootstrap function in app.ts: ionicBootstrap(MyApp, [ConnectivityService]);

      • worldnick

        So I started a new project and tried this from scratch following the tutorial exactly. “Cannot find name ‘Connection’.” – I’m thinking perhaps the navigator object is not being imported into the provider service? I don’t know how that service would know what navigator is?

      • This tutorial is not up to date with the latest version of Ionic, so it won’t work without errors if you follow it exactly. navigator is a global object, as is Connection but only when running on a device with the network information plugin installed. The issue is that TypeScript complains about these now because it doesn’t know what they are, so the easiest way is to just declare them.

      • worldnick

        I have tried doing this:

        navigator: any;
        this.Connection: any;
        navigator.connection: any;

        I get Error TS1005: ‘;’ expected.

        Could you please make an example?

        Thank you!

      • Updated the connectivity service in this post, only in isolation though, I haven’t tested the rest of the code yet.

      • worldnick

        I noticed this project is initialized with a –ts, which many of use may not have done since we are trying to add a map to an existing ionic 2 project. I’m currently looking if there is any way to add that flag after the project is initialized.

      • worldnick

        Maybe it’s because I’m running it from “ionic serve”?

  • Varshil Shah

    hey josh i used your code for check internet connectivity but i got error that is Property ‘connection’ does not exist on ‘Navigator’

    • Lisa

      use ‘type’ instead of ‘connection’

  • levantam

    Hi Josh,

    I did as instructed but it does not work!
    it’s error:

    -TypeScript error: D:/project/ionic2-advanced-maps/app/pages/map/map.ts(22,47): Error TS2304: Cannot find name ‘google’.

    -TypeScript error: D:/project/ionic2-advanced-maps/app/pages/map/map.ts(27,17): Error TS2339: Property ‘connectivity’ does not exist on type ‘MapPage’.

    -TypeScript error: D:/project/ionic2-advanced-maps/app/pages/map/map.ts(31,20): Error TS2339: Property ‘mapInit’ does not exist on type ‘Window’.

    • All your errors are simple to solve, if your not able to solve them, I recommend you to spend more time to learn more about js/ts, below how solve this errors:

      Cannot find name ‘google’, Run the command:typings install dt~google.maps –global
      Property ‘connectivity’ does not exist on type ‘MapPage’. ‘connectivity’ should be ‘connectivityService’ as declaredted in constructor
      Property ‘mapInit’ does not exist on type ‘Window’. Just remove this peace of code, isn’t necessary

      • levantam

        thank you.

  • Hi all, I’ve just updated the code to work with beta.11 which should solve all of the issues mentioned in the comments.

    • Luís Cunha

      Very nice, thx =)

    • Robert Stevens

      Hi Josh, could you do a tutorial where the user uses google places autocomplete in conjunction with the map. E.g. User selects an address in New York via input field, this then updates the map to jump to selected address.

      Also providing the User with an option to save the location for future use etc.

  • levantam

    import {Geolocation} from ‘ionic-native’
    My project not found Geolocation.
    I do not know how? I did as instructed but not

    • André Vicente

      Change ‘ionic-native’ to ‘@ionic-native/geolocation’

  • Anuranjan Srivastav

    thank you

  • Kailash

    Hey Josh, this tutorial works perfectly. But i tried to add segments(Map & List) to maps.html, but it doesn’t recognize the list view items that i have added.

  • Thanks Josh. I particularly like the Connectivity Service – simple and works very well.

  • Kailash

    if i do not use #map in map.html its returning error. I am trying to implement segments and if i put under *ngSwitchCase Maps doesn’t load at all. I think its the way we have defined in .scss file. How can i make the same code work for Segments as well?

    • I have the same issue, Have you found any solution

  • J-Yen

    I have an error when running with Cordova:
    ReferenceError: Connection is not defined
    at ConnectivityService.isOnline
    How can i fix it?

    btw: great tutorials, thank you!

    • tanzeel

      did you fix this issue ? I am getting the same error

  • Marshall Villanueva

    I’ve managed to get this to work, but my zoom controls at the bottom right of the screen are cut off. I’ve tried fixing it by doing what’s suggested in the following links, but I haven’t been successful. Any help would really be appreciated.

    http://stackoverflow.com/questions/15811911/google-maps-cut-off-in-chrome
    http://stackoverflow.com/questions/8511436/zoom-control-and-streetview-not-showing-on-my-google-map

    • f1rehead

      I hope this isn’t too late for you — change the height in home.scss to 93% or 94%. The reason is that the header gets included in the height calculation. Setting the height to 93% isn’t perfect but it works and I haven’t figured out how to put the map in fixed-content vs scroll-content.

  • martin.mildner

    hey josh, thanks for the update. one question:

    i followed your tutorial and publishing an event in my app.ts at “onOffline”:

    var onOffline = () => {
    this.events.publish(‘connection:offline’);
    }

    and on another page i am listening to this event and set a variable:

    // Subscribe to the connection offline event
    events.subscribe(‘connection:offline’, () => {
    this.connection = false;
    console.log(‘offline’);
    });

    and the page template:

    Sorry, no connection

    When I am on the page and switch to flight mode on my device console.log(‘offline’) is triggered, but the [hidden] part is not shown / the view does not change.
    Any idea? thanks for your help!!!

  • Einar

    Great tutorial! Is it possible to make the map not reload when navigating from another page, just load the map the one time the app is opened?

  • Thiago Castilho

    Hello Josh, thanks for great articles. I tried this one but I can’t figure how to implement the enable and disable functions. I tried everything but nothing works.
    The most usual behavior is that the map is hid but I can’t make it show again.

    Thanks!

  • Mario Olofo

    Hello! Nice article!
    Did it still work? In my project the new version of Angular 2 sanatizes the script.src tag and remove the google map link…

  • Francesco Polimeni

    Hi,

    I appreciated the tutorial, it works.
    I wonder if there is a way to work at higher level with the same approach as you did in your previous google maps example where you used ionic primitives like ionViewDidLoad,
    instead of using the window[…] and the document stuff that looks like you are mixing different levels of abstraction.

  • david-the-dude

    Hi, thanks for this article. Like others indicated only a blank page is shown in iOS simulators and devices. I include the logs generated by starting the App in an iPhone 5 simulator here: http://pastebin.com/wGPqkWNE. Testing with Ionic 2.0.0-rc.1. The example works fine in browsers. Any ideas?

  • Melissa Warrens

    I’m getting following error: ReferenceError: google is not defined

    Any idea? Thanks!

    • f1rehead

      Do you have
      declare var google;
      at the top of home.ts?

  • Feri Murdeni

    Hello Josh, Thanks for this tutorial.

    I have followed all the tutorial, but I find a blank map of the android emulator, but works on chrome browser.
    Can you help me, or anyone else here to help me ?. For my “app.ts” I’ve made to call loadGoogleMaps() inside ionViewDidLoad like this:
    ionViewDidLoad() {
    this.loadGoogleMaps();
    }

    Thanks,

    Thanks, I’ll waiting for your reply

    • f1rehead

      Add that function to home.ts instead

  • D Riley

    First off thank you for your tutorials! Using this tutorial I can navigate to a maps page and the map and current loc marker shows fine. However when I navigate to previous page and then back to the map I’m getting “Error in ./MapPage class MapPage_Host – caused by: Cannot read property ‘firstChild’ of null”. I seems like it isn’t trying to recreate the MapPage(in your case HomePage) object. Any thoughts? Thx.

  • Sonu

    Hi,
    I using the isonline function but every time its showing the return value true even network is on or off,below is my code

    Service.ts
    checkInternate(): boolean {
    if(this.onDevice && Network.connection){
    return Network.connection !== Connection.NONE;

    } else {
    return navigator.onLine;

    }
    }

    home.ts

    if(this.connectivityService.checkInternate())
    {
    this.navCtrl.push(page1,{
    index:”page1″
    });
    }
    else{
    this.showInternetAlertService.alert();

    }

  • nomsie king

    hello how do i put a pointer on my location were the map is currently pointing to

  • Ka Mok

    What would be the downside of just using the Ionic Native Network, set a boolean on your Connectivity Service called connected, default to true. Then, write the two Observables, Network.onConnect and Network.onDisconnect to change the boolean. Would that take out some work?

  • Shane

    Something about this is preventing the app from launching on an android device. My code is exactly as above. Any ideas?

  • Shane

    I keep getting the following error in the newest release of Ionic:
    Property ‘connection’ does not exist on type ‘typeof Network’.

    • Shane

      It looks like the method connection was replaced with type. Replacing the word connection with type throughout connectivity-service.ts fixes any problems.

      • terrycollinson1

        Thanks. i had that too

      • Thanks Shane 🙂

      • Carlos Proaño

        thanks shane

    • Alex Devoid

      I did this and it worked. Then I get the error: “You have included the Google Maps API multiple times on this page. This may cause unexpected errors.” I cannot figure out why and have spent hours and hours trying to figure it out. But the map seems to be functioning. Has anyone experienced this error?

  • james

    Hi Josh. How can I execute a function when in background mode. For example. when there is the network, the function should synchronize the sqlite database with the remote mysql database. Specifically ionic 2.

  • Luís Cunha

    I am not able to run this successfully on an android device, I just get a blank space where the map should be. On the web is works as expected though.

    • Carlos Proaño

      i got the same problem when i run it on an android virtual device i got a blank page but not the map i guess this is because only works for web but not for mobile

      • ng_gopi

        have u clear that Issue @disqus_d04GKY716u:disqus . b’coz i am getting same issue.in web it works perfectly but in android ionicView app showing blank page. will u please provide any solution thanks in advance.

      • Carlos Proaño

        no solution

  • Alex Mayer

    This used to work, but now I get the Following exception:

    ORIGINAL EXCEPTION: Connection is not defined

    any Idea what happened? thanks in advance

  • Ahmed Atbara

    Very nice tutorial, Josh!
    I have a little solution for those who ran into this error:
    ———–
    [18:43:54] typescript: src/providers/connectivity-service.ts, line: 20
    Property ‘connection’ does not exist on type ‘typeof Network’.
    ———-
    Please modify the all the “Network.connection” in the provider “connectivity-service.ts” file to “Network[‘connection’]”, and that should resolve this issue, modify it everywhere in the file. I don’t why it does that for me but that how I solved it.
    I created this app using “ionic tabs” version.

    • Ahmed Atbara

      You can also replace it with “Network.type” too, it will fix this issue.

    • Cynthia Dewi

      thanks! its work when “Network.type” cant fix it

  • Eric Lara Amat

    Hi Josh, great job with this tutorial but at this moment it’s outdated. Checking https://ionicframework.com/docs/v2/native/network/ would you suggest to check connection directly on page component or following the same service approach?
    Thanks

  • hardik

    can you give me example of turn by turn navigation in maps in ionic 2 with all three platform support Android, IOS and Windows?

  • pravallika

    Hi Josh,
    I need could you do a tutorial of google charts integration??

  • John

    > Cannot find module “ionic-native”

    Keep getting this issue when I work through your tutorials.

  • Braian Mellor

    I just got a blank page and this on console

    xcrun: error: unable to find utility “PackageApplication”, not a developer tool or in PATH

    Error: Error code 72 for command: xcrun with args: -sdk,iphoneos,PackageApplication

  • Moreshwar Sambare

    Cannot find module “ionic-native”

    hepl me

  • John Johnny

    I have added the google app into an ionic-modal. The map-ready event is triggered, but nothing shows up when run on iOS Simulator or device. Just a blank transparent screen. What could be wrong that the map is not visible but the google map api is called.

  • Vesper

    deberias de actualizar tu codigo ya que mucho de lo que aqui pones ya no funciona

  • chatur priyono

    Hi Josh,
    on the web browser simulator not show error, but when i debug with google chrome on console show error:
    Uncought Vm2000 js?key=AI…….&callback=initmap
    initmap is not a function
    name:”invalidvalue error”
    google maps API warning:
    no apikey

    google maps api error
    apiNotActifitedmap error

  • chatur priyono

    Hi Josh, thank u for your article, it’s runing well on my laptop.
    next step from here is, how to add places search box and then save coordinat to database, i’m found on https://developers.google.com/maps/documentation/javascript/examples/places-searchbox but i’m not yet success to implement . i hope you create a article about this.
    Thank you

  • rameshkumar konda

    Hi all
    i am following your steps but i am get run time error: Runtime Error
    Cannot find module “ionic-native”
    Stack
    Error: Cannot find module “ionic-native”
    at Object. (http://localhost:8100/build/main.js:55768:7)
    at __webpack_require__ (http://localhost:8100/build/main.js:48:30)
    at Object. (http://localhost:8100/build/main.js:55819:72)
    at __webpack_require__ (http://localhost:8100/build/main.js:48:30)
    at Object. (http://localhost:8100/build/main.js:55714:81)
    at __webpack_require__ (http://localhost:8100/build/main.js:48:30)
    at Object. (http://localhost:8100/build/main.js:55676:67)
    at __webpack_require__ (http://localhost:8100/build/main.js:48:30)
    at Object. (http://localhost:8100/build/main.js:74538:75)
    at __webpack_require__ (http://localhost:8100/build/main.js:48:30)
    Ionic Framework: 3.2.1
    Ionic Native: ^3.5.0
    Ionic App Scripts: 1.3.7
    Angular Core: 4.1.0
    Angular Compiler CLI: 4.1.0
    Node: 7.8.0
    OS Platform: Linux 4.4
    Navigator Platform: Linux x86_64
    User Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

  • Chris Scutt

    I solved the ‘Cannot find module “ionic-native” problem by adjusting the connectivity service by first updating as Ahmed Atbara suggested so Network.connectivity become network.type. This still did not solve the problem as ionic-native now no longer exists. All modules are individually added from @ionic-native/plugin so I added the cordova plugin as Josh instructed but then added ‘npm install @ionic-native/network’ and changed references to this in the ConnectivityService as well as importing Network on the app.module.ts file. Because Network is in my constructor as ‘public network: Network’ I also changed all Network.type to network.type. With all this done, the ionic-native error was gone! I hope this helps! I have put my updated ConnectivityService below:

    ________________________________________________________________________________________________________________________________________

    import { Injectable } from ‘@angular/core’;
    import { Network } from ‘@ionic-native/network’;
    import { Platform } from ‘ionic-angular’;

    declare var Connection;

    @Injectable()
    export class ConnectivityService {

    onDevice: boolean;

    constructor(public platform: Platform, private network: Network){
    this.onDevice = this.platform.is(‘cordova’);
    }

    isOnline(): boolean {
    if(this.onDevice && this.network.type){
    return this.network.type !== Connection.NONE;
    } else {
    return navigator.onLine;
    }
    }

    isOffline(): boolean {
    if(this.onDevice && this.network.type){
    return this.network.type === Connection.NONE;
    } else {
    return !navigator.onLine;
    }
    }
    }

    • Thinker

      Have you found a way to fix this

  • Mauro

    I’ve putted the map component in a dedicated page. When I start the application and navigate to that page the map won’t load, if I go back and then reload the page everything works fine. I resolved this issue by putting

    this.initMap();
    this.enableMap();

    at the end of the first if statement in loadGoogleMaps(), so my method now is:

    loadGoogleMaps() {

    this.addConnectivityListeners();

    if(typeof google == “undefined” || typeof google.maps == “undefined”) {
    console.log(“Google maps Javascript needs to be loaded”);
    this.disableMap();

    if(this.connectivity.isOnline()) {
    console.log(“online, loading map”);

    //Load the SDK
    window[‘mapInit’] = () => {
    console.log(“loading the SDK”);
    this.initMap();
    this.enableMap();
    }

    let script = document.createElement(“script”);
    script.id = “googleMaps”;

    if(this.apiKey) {
    script.src = ‘http://maps.google.com/maps/api/js?key=’ + this.apiKey + ‘&callbaack=mapInit’;
    }
    else {
    script.src = ‘http://maps.google.com/maps/api/js?callbaack=mapInit’;
    }
    document.body.appendChild(script);
    this.initMap();
    this.enableMap();
    }
    }
    else {
    if(this.connectivity.isOnline()) {
    console.log(“showing map”);
    this.initMap();
    this.enableMap();
    }
    else {
    console.log(“disabling map”);
    this.disableMap;
    }
    }
    }

    I’m not sure that this is the best way to resolve it, if anyone has any suggestion please share it

  • Nicolas Behra

    Hi,
    There’s an update to do with the Network, because it’s actually in @ionic-native

    npm install @ionic-native/network –save

    and update the connectivity.service.ts to:

    import { Injectable } from ‘@angular/core’;
    import { Network } from ‘@ionic-native/network’;
    import { Platform } from ‘ionic-angular’;

    declare var Connection;
    /*
    Generated class for the ConnectivityService provider.

    See https://angular.io/docs/ts/latest/guide/dependency-injection.html
    for more info on providers and Angular 2 DI.
    */
    @Injectable()
    export class ConnectivityService {

    onDevice: boolean;

    constructor(
    public platform: Platform,
    private network: Network) {
    console.log(‘Hello ConnectivityService Provider’);
    this.onDevice = this.platform.is(‘cordova’);
    }

    isOnline(): boolean {
    if(this.onDevice && this.network.type){
    return this.network.type !== Connection.NONE;
    } else {
    return navigator.onLine;
    }
    }

    isOffline(): boolean {
    if(this.onDevice && this.network.type){
    return this.network.type === Connection.NONE;
    } else {
    return !navigator.onLine;
    }
    }

    }

    You have to import Network as a provider in app.module.ts

    Hope what have I done is correct and helpfull 🙂

  • Josh,

    Is it possible to draw on a Map in Ionic? Google offers a lib for this: https://developers.google.com/maps/documentation/javascript/drawinglayer but I haven’t been able to figure it out in Ionic yet. I want the user to be able to draw a search area on the map the same way you can in Zillow or any other Real Estate app… Any thoughts? Thanks!

  • Ivan More Flores