Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize Google Map in AngularJS

I am considering migrating from backbonejs to angularjs.

In backbone I am able to initialize a view at which point I create an instance of google map. I can then pan/zoom/etc and switch between views and not lose the current state of the map.

Given the following using angularjs:

layout.html

<body>
  <div class="container-fluid" ng-view></div>

map.html

<div id="map_canvas" ng-controller="MapCtrl"></div>

I was able to create a directive to render a map just fine. Problem is that it reloads the map each time I switch back to the map view.

<map></map>

So from what I am learning about Angular, I figured I would create a MapController and initialize the map there. No success.

Bottom line is I need to async-init a google map and push data to it locally or remotely AND be able to navigate the app without RELOADING the map from scratch each time.

Can someone suggest the correct approach?

Thank you :)

Attempt Per Andy Joslin suggestion:

In app.js:

// Generated by CoffeeScript 1.3.3
(function() {
  "use strict";

  angular.module("ofm", ["ofm.filters", "GoogleMaps", "ofm.directives"]).config([
    "$routeProvider", "$locationProvider", function($routeProvider, $locationProvider) {
      $routeProvider.when("/", {
        templateUrl: "partials/home"
      }).when("/map", {
        templateUrl: "partials/map",
        controller: MapCtrl
      }).otherwise({
        redirectTo: "/"
      });
      return $locationProvider.html5Mode(true);
    }
  ]);

}).call(this);

In services.js:

angular.module('GoogleMaps', []).
  factory('wasMapInitialized', function() {
    console.log("inside service");
    var maps = 0;

    if (!maps) {
      maps += 1;
      return 0;
    } else {
      return 1;
    }
  });

In controllers.js:

function MapCtrl($scope) {
  if (!GoogleMaps.wasMapInitialized()) {
    var lat = 46.87916;
    var lng = -3.32910;
    var map_id = '#map';
    initialize(map_id, lat, lng);
  }
  function initialize(map_id, lat, lng) {
    var myOptions = {
      zoom : 8,
      center : new google.maps.LatLng(lat, lng),
      mapTypeId : google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map($(map_id)[0], myOptions);
  }
}

In map.html

#map
<div ng-controller="MapCtrl"></div>

I get Error: Unknown provider: GoogleMapsProvider <- GoogleMaps

like image 855
Larry Eitel Avatar asked Jun 24 '12 19:06

Larry Eitel


2 Answers

Since views create and destroy controllers when the view changes, you want your maps data to persist somewhere else. Try creating a GoogleMap service which will store the data.

myApp.factory('GoogleMaps', function() {
  var maps = {};

  function addMap(mapId) {
    maps[mapId] = {};
  }
  function getMap(mapId) {
    if (!maps[mapId]) addMap(mapId);
    return maps[mapId];
  }

  return {
    addMap: addMap,
    getMap: getMap
  }
});

function MyController($scope, GoogleMaps) {
  //Each time the view is switched to this, retrieve supermanMap
  $scope.map = GoogleMaps.getMap('supermanMap');

  $scope.editMap = function() {
    $scope.map.kryptonite = true;
  };
}

If you don't like this solution, there are some other ways to do it too.

like image 157
Andrew Joslin Avatar answered Nov 12 '22 20:11

Andrew Joslin


This is what I am doing in Backbone to keep the view instead of destroying it. Suppose you have a div with id="container" and your router have the corresponding routes.

routes: {
    "":"home",
    "map": "showMap"
},

showMap: function() {
    $("#container").children().detach();
    if(!this.mapView) {
        this.mapView = new MapView(); 
        this.mapView.render();
    }
    $("#container").html(this.mapView.el);
}
like image 1
Jerry Avatar answered Nov 12 '22 20:11

Jerry