[solved] Multiple Google Maps (v3) inside ion-item with ng-repeat and ng-show


#1

After two days of searching and searching and searching for solutions and yet no wanted results I’ve decided I need help. It seems like it hasn’t been tried before so I’ll reproduce my situation as coherent and complete possible.

In short, the goal:

  1. To have an ion-list repeat ion-items via ng-repeat with data from
    the controller.
  2. These ion-items represent a title and a piece of information linked to that title, three times.
  3. The “information”-ion-items are hidden when entering the page and can be opened by clicking their title (using ng-show).
  4. Inside each “information”-ion-item I want to show a google map, with data from the controller, when opened.

Problem:
Even after calling google.maps.event.trigger($scope.map, ‘resize’); there are still grey tiles. Yes, I have tried timeout, google maps’ eventlistener when map is idle, ng-if, document ready stuff, directives, creating the maps on an opened ion-item and then hide when loaded, $ionicPlatform.readt(function…), cordova whitelist, ng-map plugin, other plugins,… nothing works.

What I want it to do:
It should just open a “information”-ion-item when a title is clicked. It should load a map from data, put it in the div (yes, css is styled correctly and I’ve set max-width: none, and height to a fixed size in px), resize it and call it a day.

Please. Help. It’s. Killing. Me.

Updated plunker: http://plnkr.co/edit/BwZk9V534pIRkWADFjjw?p=preview as you can see in a browser it works fine but on my smartphone it resizes but still shows grey tiles…

Thanks already for the support!


#2

Hi @Brock01,
It was always displaying but in item 1. Some of you code was a bit weird. Your $timeout is always not a function (Not sure what the timeout is for).

Here is my tweaked version:
controller:

.controller('MainController', ['$scope', function($scope, $timeout) {

  $scope.items = [{"id":"Item One","point_lat":"51.26278276402000","point_lng":"4.41978687426830"},{"id":"Item Two","point_lat":"51.19422807197800","point_lng":"4.43719657638180"},{"id":"Item Three","point_lat":"51.21825905664000","point_lng":"4.37095593221650"}];
  var mapOptions = {
    zoom: 15,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  $scope.toggleGroup = function(group) {
    if ($scope.isGroupShown(group)) {
      $scope.shownGroup = null;
    } 
    else {
      $scope.shownGroup = group;
      for(var i = 0; i < $scope.items.length; i++){
        var item = $scope.items[i];
        // search for opened item in the array of items
        if(item.id == group){ // found item
          // make latitude-longitude element
          var myLatlng = new google.maps.LatLng(item.point_lat, item.point_lng);

          // make map-element
          $scope.map = new google.maps.Map(document.getElementById('map' + item.id), mapOptions);
          
          // make marker-element
          var marker = new google.maps.Marker({
            position: myLatlng,
            map: $scope.map
          });
          
          // resize map now
          google.maps.event.trigger($scope.map, 'resize');
          $scope.map.setCenter(myLatlng);
          $scope.map.setZoom( $scope.map.getZoom() );
          
          // resize map when map is idle.
          google.maps.event.addListenerOnce($scope.map, 'idle', function() {
            console.log("map idled, resizing");
            google.maps.event.trigger($scope.map, 'resize');
            $scope.map.setCenter(myLatlng);
            $scope.map.setZoom( $scope.map.getZoom() );
          }); // shouldn't be making a function inside a loop but F it i'm trying everything, 
        }
      }
      // resize map on time out (5 seconds)
      $timeout(function(){
        console.log("timeout, resizing");
        google.maps.event.trigger($scope.map, "resize");
        $scope.map.setCenter(myLatlng);
        $scope.map.setZoom( $scope.map.getZoom() );
      }, 5000);
    }
  }

  $scope.isGroupShown = function(group) {
    return $scope.shownGroup === group;
  };

}]);

index.html:

//In Head    
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>

<body ng-app="starter" ng-controller="MainController">
    <ion-list ng-repeat="item in items">
      <ion-item  class="text-center item-accordion item-icon-left item-header" ng-click="toggleGroup('{{item.id}}')">
        {{ item.id }}
      </ion-item>
      <ion-item class="item-accordion item-text-wrap" ng-show="isGroupShown('{{item.id}}')">
        <div class='parkmap' id='map{{item.id}}'></div>
      </ion-item>
    </ion-list>
  </body>

style.css:

.parkmap{
	height:300px;
}

Hope all works fine for you.


#3

Yes, that previous plunker was just a piece of crap tbh (I had to go fast yesterday) but i’ve updated with a better example…

I’ve tried your adjustments but it’s not really changing anything crucial (except for the injection and less css?). Have you built it and tested it on a smartphone?

I’m guessing it has something to do with the ionic framework and the ion-items or something (being hidden and such). The code in the controller should be fine (though messy I may agree).


#4

Your code is working on my HTC M7 & Desktop (Ripple Emulator). Plus you don’t really need a google API key, just add this to the head:

<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>

Screenshot from HTC M7 (5.0.2):


#5

Hmm… I’ve tried it with my girlfriend’s nexus 4 and it’s not working there. It says ReferenceError: google is not defined. This could have something to do with the whitelist. At least I have a trail here and I can look a bit more into it…

(I have a huawei G6 4G, it doesn’t give that error but yeah, it does give those grey tiles…)


#6

It has something to do with the script tag for Google. Place it above other app.js & controllers.js, that’s how mine is, not outside the head tag. You could refer to this link: http://stackoverflow.com/questions/24704063/google-map-error-uncaught-referenceerror-google-is-not-defined-yeoman


#7

First of all, thanks zachary545 for your help! That script-tag wasn’t exactly the problem but by trying more and more I found out it just had to be something with the whitelist.

So I restarted a blank project. Copied all files from /www folder, re-installed the whitelist plugin and I be damned, it’s working now!

Praise the Ionic overlords, off to more developping and progress, huzzah!


#8

Not a problem @Brock01, happy to help! Happy Coding! :smiley:


#9

hi there @Brock01
so i am to do similar thing like
and not getting any thing back so do u think that its only the white list thing or its some thing else since i just installed my whitelist plugin and my map is blank


is it this what was with u or this is new?
regards


#10

Maybe you could post your code on codepen or plnkr, it could be something you miss.


#11

@zachary545 i tried to make plnker but ive never tried it before so i couldnt make it run but ot looks like i found my problem becuase am using the exactly the same code above with only one diffrence.
i am using a modal and it seems that if the map is not shown in the first page it will never load i tried the code in a new project and it worked if its in the first loaded page other than that it wont load

so guys if any body now a dirictive which i can use with the above code to show the maps in any page (i prefer modal) other than the first page please let me know about it
im getting bored with that

regards


#12

this a link of a project i created please check ithttps://www.dropbox.com/sh/u3dvlz7th47ao6k/AAD5SsR-Xvxdn-FuITM7bA-za?dl=0


#13

Hi @warbadev,
Didn’t get a chance to look at your code. I am using @Brock01 code with my modifications.

controller.js:

angular.module('starter.controllers', [])

.controller('DashCtrl', function($scope, $timeout, $ionicModal) {
    $scope.items = [{
      "id": "Item One",
      "point_lat": "51.26278276402000",
      "point_lng": "4.41978687426830",
      "code": "10"
    }, {
      "id": "Item Two",
      "point_lat": "51.19422807197800",
      "point_lng": "4.43719657638180",
      "code": "20"
    }, {
      "id": "Item Three",
      "point_lat": "51.21825905664000",
      "point_lng": "4.37095593221650",
      "code": "30"
    }];
    var mapOptions = {
      zoom: 15,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    $scope.toggleGroup = function(group) {
      if ($scope.isGroupShown(group)) {
        $scope.shownGroup = null;
      } else {
        $scope.shownGroup = group;
        for (var i = 0; i < $scope.items.length; i++) {
          var item = $scope.items[i];
          // search for opened item in the array of items
          if (item.id == group) { // found item
            // make latitude-longitude element
            var myLatlng = new google.maps.LatLng(item.point_lat, item.point_lng);

            $scope.itemCode = item.code;
            console.log($scope.itemCode);

            // make map-element
            $scope.map = new google.maps.Map(document.getElementById("map"), mapOptions);

            console.log($scope.map);

            // make marker-element
            var marker = new google.maps.Marker({
              position: myLatlng,
              map: $scope.map
            });

            // resize map now
            google.maps.event.trigger($scope.map, 'resize');
            $scope.map.setCenter(myLatlng);
            $scope.map.setZoom($scope.map.getZoom());

            // resize map when map is idle.
            google.maps.event.addListenerOnce($scope.map, 'idle', function() {
              console.log("map idled, resizing");
              google.maps.event.trigger($scope.map, 'resize');
              $scope.map.setCenter(myLatlng);
              $scope.map.setZoom($scope.map.getZoom());
            }); // shouldn't be making a function inside a loop but F it i'm trying everything, 
            break;
          }
        }
        // resize map on time out (5 seconds)
        $timeout(function() {
          console.log("timeout, resizing");
          google.maps.event.trigger($scope.map, "resize");
          $scope.map.setCenter(myLatlng);
          $scope.map.setZoom($scope.map.getZoom());
        }, 5000);
      }
    };

    $scope.isGroupShown = function(group) {
      return $scope.shownGroup === group;
    };

    // Create the modal
    $ionicModal.fromTemplateUrl('modal.html', function($ionicModal) {
    $scope.modal = $ionicModal;
    }, {
        // Use our scope for the scope of the modal to keep it simple
        scope: $scope,
        // The animation we want to use for the modal entrance
        animation: 'slide-in-up'
    });

    $scope.openModal = function(id) {
        $scope.id = id;
        console.log($scope.id);
        if($scope.id){
          $scope.modal.show();
          $scope.toggleGroup($scope.id);
        }
    }
});

modal.html:

<ion-modal-view>
<ion-header-bar class="bar bar-header">
  <h1 class="title">Map Modal</h1>
  <button class="button button-icon button-clear ion-android-close" ng-click="modal.hide()" style="padding-left:10px;padding-bottom:10px"></button>
</ion-header-bar>
<ion-content class="padding">
    <div class='parkmap' id="map"></div>
</ion-content>
</ion-modal-view>

tab-dash.html:

<ion-view title="Dashboard">
  <ion-content class="has-header padding">
    <ion-list ng-repeat="item in items">
        <ion-item ng-click="openModal(item.id)">
          {{ item.id }}
        </ion-item>
      </ion-list>
  </ion-content>
</ion-view>

style.css:

.parkmap{
  height: 300px;
  width: 100%;
  max-width: none;
}

Hope it helps you.


#14

thanks ill try to work with it now the think is your code is to open a modal after clicking the list item … what am trying to do is to use the original code in a modal which means all the list and the map in a single modal