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 :)

Success!!! per Andy Joslin's 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:

'use strict';

var app = angular.module('ofm.services', []);

app.factory('GoogleMaps', function() {

  var map_id  = '#map';
  var lat     = 46.87916;
  var lng     = -3.32910;
  var zoom    = 15;
  var map     = initialize(map_id, lat, lng, zoom);

  return map;
});

function initialize(map_id, lat, lng, zoom) {
  var myOptions = {
    zoom : 8,
    center : new google.maps.LatLng(lat, lng),
    mapTypeId : google.maps.MapTypeId.ROADMAP
  };
  return new google.maps.Map($(map_id)[0], myOptions);
}

In controllers.js:

function HomeCtrl($scope) {
  $('#map').hide()
  $('.container-fluid').show()
}

function MapCtrl($scope, GoogleMaps) {
  $scope.map = GoogleMaps;
  $('#map').show()
  $('.container-fluid').hide()
}

MapCtrl.$inject = ['$scope','GoogleMaps'];

In map.html

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

In index.jade

extends layout

block body
  #map 
  .container-fluid(ng-view)  
  include /partials/scripts

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.

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);
}