Cordova-plugin-googlemaps: MAP_READY doesn't load on second Instance

Created on 5 Sep 2017  路  14Comments  路  Source: mapsplugin/cordova-plugin-googlemaps

I'm submitting a ... (check one with "x")
[ x ] question
[ ] any problem or bug report
[ ] feature request

The plugin version: (check one with "x")
[ ] 1.4.x
[ x ] 2.0.0-beta3

If you choose 'problem or bug report', please select OS: (check one with "x")
[ ] Android
[ ] iOS

cordova information: (run $> cordova plugin list)

cordova-plugin-googlemaps 2.0.0-beta3-20170903-1743 "cordova-plugin-googlemaps"

Current behavior:

The map logic is inside the MapsPage, when I enter to the MapsPage the map loads correctly, from there I go to another page, and from that page I go again to the MapsPage (pushing the page, not popping it from the navigation stack), now the map never hits the MAP_READY event.
I don't want to destroy the first map, because I might go back to it later.

What am I missing to see the expected behavior?

Environment info:
local packages:
ionic/app-scripts : 2.1.3
Cordova Platforms : android 6.2.3
Ionic Framework : ionic-angular 3.6.0
System:
Android SDK Tools : 25.1.3
Node : v6.11.2
npm : 5.0.4
OS : Windows 10

Expected behavior:

The map should hit the MAP_READY event again (the second time I enter to the MapsPage), with a new id for the map.

Steps to reproduce:

  1. Add maps plugin
  2. Go to the Maps Page
  3. Go from the MapsPage to a second page
  4. Go from that second page to the MapsPage (pushing the MapsPage, not popping it)
  5. The MAP_READY event doesn't fire again

Screen capture or video record:

Related code, data or error log (please format your code or data):

Code for the Maps Page:

.ts file:

  map: any;
  selectedMarker: {
    title: string,
    snippet: string
  }
  constructor(
    private navCtrl: NavController,
    private platform: Platform) {
    this.setSelectedMarker("Hello Friend...", "隆隆隆Click Me!!!");
    let mapCenter: LatLng = new LatLng(-17.3829278, -66.1596725);
    setTimeout(() => {
      this.loadMap(mapCenter).then(success => {
        this.addMarker(mapCenter);
      });
    }, 1)
  }

  private setSelectedMarker(title: string, snippet: string) {
    this.selectedMarker = {
      title: title,
      snippet: snippet
    }
  }

  private loadMap(mapCenter: LatLng): Promise<boolean> {
    var promise: Promise<boolean> = new Promise<boolean>(resolve => {
      this.platform.ready().then(() => {
        console.log("Platform ready!");
        let element = document.getElementById('map');
        this.map = (<any>window).plugin.google.maps.Map.getMap(element, this.getMapConfigurations(mapCenter));
        this.map.one((<any>window).plugin.google.maps.event.MAP_READY, map => {
          console.log("Map Ready!");
          resolve(true);
        });
      });
    });
    return promise;
  }

  private addMarker(pinPos: LatLng) {
    let markerOptions: MarkerOptions = {
      position: pinPos,
      title: "Hello",
      snippet: "World!"
    }
    this.map.addMarker(markerOptions);
  }

  private goToSecondMap() {
    this.navCtrl.push(BlackPage);
  }

  private getMapConfigurations(mapCenter: LatLng) {
    return {
      'controls': {
        'compass': true,
        'myLocationButton': true,
        'indoorPicker': true,
        'zoom': false
      },
      'gestures': {
        'scroll': true,
        'tilt': true,
        'rotate': true,
        'zoom': true
      },
      'camera': {
        'latLng': mapCenter,
        'tilt': 10,
        'zoom': 15,
        'bearing': 15
      }
    }
  }

.html file:

<ion-header>

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

<ion-content>

  <div class="mapsSpace">
    <div id="map" class="map"></div>
  </div>

  <div class="noMapSpace" on-tap="goToSecondMap()">
    <div class="hostSpace">
      <div class="hostInfo">
        <div class="hostAddress">{{selectedMarker.title}}</div>
        <div class="hostAddress">{{selectedMarker.snippet}}</div>
      </div>
    </div>
  </div>

</ion-content>

.scss file:

ion-app._gmaps_cdv_ .nav-decor {
    background-color: transparent;
    display: none !important;
  }

  page-maps {
    .mapsSpace{
      height: 100%;
    }

    .map {
      height: 100%;
    }

    .noMapSpace {
      z-index: 1000;
      opacity: 0.8;
      border-radius: 10px;
      display: flex;
      justify-content: center;
      position: absolute;
      bottom: 12vh;
      left: 5vw;
      height: 15vh;
      width: 90vw;
      padding: 5px 0;
      background-color: #1C1C1C; //border: solid 2px color($colors, darkGray);
    }

    .hostSpace {
      margin: 0;    
      display: flex;
      align-items: center;
      justify-content: center; //background-color: $cardBackgroundColor;
      border-radius: 10px;
    }

    .hostInfo {
      width: 65vw;
      padding: 0 10px;
    }

    .hostAddress {
      color: white;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
}



If your problem is solved, please consider small amount donation to this project.
Appreciate for your kindness.
https://github.com/mapsplugin/cordova-plugin-googlemaps-doc/blob/master/README.md#buy-me-a-beer

not bug wontfix

All 14 comments

Please share your project file on github or others.

@wf9a5m75 I invited you to the repo

Thank you. I noticed one thing you use old version of @ionic-native/core.
https://github.com/Guchster/googleMaps-plugin-demo-app/blob/master/package.json#L23-L24

You need to use @ionic-native/core version 4.2.1, or higher

@wf9a5m75 you are right, I updated @ionic-native/core to version ^4.2.1, however the problem remains

Ok, I'm building your app currently. Please wait for a while.

I noticed you don't use the @ionic-native/google-maps ...

I see. This is not bug.

Since you display the same map page twice times, you are trying to create map views for the same map div.
This plugin does not allow it.

If you want to do that,

  • you need to map.remove() / map.getMap() or // regenerate map instance every times
  • map.setDiv(null) / map.setDiv(mapDiv) // keep the one instance

That's the problem, as you said I am trying to create two map views for the same map div.
I don't understand though how to keep one instance of the map.
I am trying to save the map instance in a provider (dataManager), and if it's not empty when I enter the maps page, i assign to it the current mapDiv.

Like this:

  private loadMap(mapCenter: LatLng): Promise<boolean> {
    var promise: Promise<boolean> = new Promise<boolean>(resolve => {
      this.platform.ready().then(() => {
        let mapDiv = document.getElementById('map');
        let map = this.dataManager.getMap();
        if (map == null) {
          this.map = (<any>window).plugin.google.maps.Map.getMap(mapDiv, this.getMapConfigurations(mapCenter));
          this.map.one((<any>window).plugin.google.maps.event.MAP_READY, map => {
            console.log("Map Ready!");
            this.dataManager.setMap(map);
            resolve(true);
          });
        } else {
          this.map = map;
          this.map.setDiv(mapDiv);
          resolve(true);
        }
      });
    });
    return promise;
  }

However is not working, what would be the correct way to use the map.setDiv(mapDiv) in this case?
Is this logic even going on the right path?

Check out this project.
https://github.com/carvemerson/map

@wf9a5m75 Could you recommend a project for me to check out, if I wanted to regenerate the map instance every time, instead of keeping one instance?
I would be very helpfull if I could see a project that does this with map.remove() / map.getMap() as you suggested.
Thanks a lot!

I have the same issue with my application. The map only load once. At the second time the div is empty in my screen but something I saw debugging my app is inside the div appears this:

__pluginmapid="map_0_XXXXXXXXX"

Every time i load the same page the value change to "map_1_XXXX", "map_2_XXX"..
How I can fix this issue to get always the map? I tried with those examples and is still not working.

Thanks in advance.

@guillermo-medina i saw this problem a couple of weeks ago, if you are using map.remove() / map.getMap() then this may help:
on ionViewWillEenter add this:

    const mapDiv = document.createElement('DIV');
    mapDiv.setAttribute('id','maps');
    mapDiv.setAttribute('class','maps'); //define this class according to your css
    document.getElementById('mapParent').appendChild(mapDiv);

on ionViewWillLeave add this:
document.getElementById('maps').remove();
on your html do this:

    <div id='mapParent' class="mapsSpace"> //mapsSpace = class with height: 100%;
        <!--div #maps id="maps" class="maps"></div-->
    </div>

the commented line in html is where the map div will be appended, so you don't need to put it, it's just for clarification of what happens.
If my understanding is correct the html remains in the DOM, and when you load the same page it duplicates the commented div, and this plugins has a problem to find the div to which you are appending the map to when there is more than one div with the same id (in the entire app), so thats why you need to add it and remove it every time you visit the page (to ensure that there are no two divs with the same id in the DOM).
Hope it helps

PS: I had bad experiences using the ionic-native wrapper for this plugin, avoid using it when possible, the error you describe only happened when using the ionic-native wrapper

Was this page helpful?
0 / 5 - 0 ratings