Utilize the existing Google Maps API instance within a single-page application

Imagine I have a Single Page Application (Angular JS application), and I create a Google Map instance on an element with the id googleMap -

var mapInstance = new google.maps.Map(document.getElementById(`googleMap`), mapOption)

Later on, as I navigate through the application routing, I end up destroying the googleMap DOM element. When I return to the route with this element, I need to re-draw the map on it.

What is the proper way to redraw the map?

According to this answer, I shouldn't recreate it, but rather use the same instance.

Answer №1

It's important to proceed with caution when using the following code:

$scope.on('$destroy', function(){
    mapInstance = null;
})

In my experience, I encountered issues with memory usage due to old map instances lingering in the heap. This was particularly noticeable when navigating between pages and creating new map instances without properly removing the old ones from memory.

The recommended approach, as suggested in the linked answer, is to re-use your map instance instead of constantly removing and recreating it. To implement this, I created a solution where I passed the directive element to a service and dynamically created or appended the map within that element. Here is an example of how this can be implemented:

ng-view Element

<map-container></map-container>

Directive

angular.module('project')
  .directive('mapContainer', function($timeout, mapService) {
     return {
       template: '<div></div>',
       restrict: 'E',
       replace: true,
       link: function(scope, element) {
         $timeout(function () {
           mapService.createMap(element).then(function() {
              //map creation complete
           });
        });
      }
    };
 })

Service

angular.module('project')
  .service('mapService', function($q) {

    var lat = -33.1798;
    var lng = 146.2625;
    var minZoom = 5;
    var maxZoom = 20;
    var zoom =  6;
    var mapOptions = null;
    var map = null;

    function initialiseGmap(element) {

      return $q(function (resolve) {
        if (map) {
          element.append(map.getDiv());
          resolve();
        } else {
          element.append('<div id="map_canvas"></div>');

          mapOptions = {
            zoom: zoom,
            center: new google.maps.LatLng(lat, lng),
            styles: hybridMap,
            minZoom: minZoom,
            maxZoom: maxZoom,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            mapTypeControl: false,
            streetViewControl: false,
            panControl: false,
            scaleControl: true,
            zoomControl: false
          };

          map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);

          resolve();
        }
      });
    }

    return {
      createMap: function(elem) {
        return initialiseGmap(elem);
      },
      getMap: function() {
        return map;
      },
      getZoom: function() {
        return zoom;
      },
      setZoom: function(value) {
        map.setZoom(zoom);
      }

      // Additional functions for interacting with the map object can be added here as needed
    };
  });

Answer №2

This question appears to be related to AngularJS based on the presence of the angularjs tag. It is generally recommended not to handle this functionality within the page controller in an Angular JS application.

One option is to utilize an existing directive such as https://angular-ui.github.io/angular-google-maps/#!/, or you could develop your own custom directive to achieve the desired functionality.

When creating your own directive, it is important to ensure that you properly destroy the Google Map instance each time the directive is destroyed. This can be accomplished by using the $scope.on('$destroy', fn) event as shown below:

$scope.on('$destroy', function(){
    mapInstance = null;
})

Answer №3

Each instance you make a call:

map = new google.maps.Map(document.getElementById('xx'), mapOptions);

Your Google maps quota gets used up. Proceed with caution!

Answer №4

When I was facing a similar problem, I found that re-initializing Google Map with a timeout was the solution that worked for me.

 setTimeout(function(){ initialize() }, 50);

It is also possible to "kill" the initialized instance by destroying the previously dynamically created element, although this method can be more challenging...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What are the best ways to condense this JavaScript snippet?

Seeking suggestions for enhancing my coding skills. How can this code be optimized for brevity and efficiency? var resultsConstructionYear = readCookie('constructionYear'); switch (resultsConstructionYear) { case 3: document.getEleme ...

Having difficulty aligning ListItem to the right within a List

I am working with an array that contains objects which I need to display in ListItems of a List. My goal is to show these ListItems from the array Objects in a layout where odd numbers are on the left and even numbers are on the right. However, I am facing ...

Tips for managing open and closed components within a React accordion and ensuring only the clicked component is opened

Unique Accordion component: const CustomAccordion = (props: AccordionProps) => { const { label, levels, activeId, id } = props const [isExpand, setIsExpand] = useState(false) const onPress = useEvent(() => { setIsExpand( ...

Navigating through a Single Page Application (SPA) can be achieved without

Can the CSS (Level 4) @document rule handle URLs that have the # symbol or include query parameters? For those who are not familiar with this topic Currently, only Firefox supports this feature with the @-moz-document prefix. If other browsers start supp ...

How do you manage dependencies for nested components within Angular2?

Encountering an Issue: browser_adapter.js:76 Error: Cannot resolve all parameters for NestedComponent(undefined). Make sure they all have valid type or annotations. at NoAnnotationError.BaseException [as constructor] Diving Deeper Into the Problem: ...

Is there a way to retrieve an Excel file from a specific physical location using AngularJS?

Hey there, I'm looking to download an Excel file with just a click of a button. Let me walk you through the situation: Initially, I've generated an Excel file dynamically during runtime. It's saved in my project folder. However, I'm ...

Restarting an Angular app is necessary once its HTML has been updated

I've encountered an interesting challenge with an application that combines MVC and Angular2 in a not-so-great way. Basically, on the Index page, there's a partial view loading the Angular app while also including all the necessary JavaScript li ...

Having trouble getting my angular form validation to function properly

Even though I disabled Bootstrap's validation while using Angular, the validation for every input field still doesn't work. It seems like I have everything set up correctly. My code looks like this below with no success on input validation: < ...

Navigating through embedded arrays in Angular

JSON Object const users = [{ "name":"Mark", "age":30, "isActive" : true, "cars":{ Owned : ["Ford", "BMW", "Fiat"], Rented : ["Ford", "BMW", "Fiat" ...

The Nuxt image keeps disappearing every time I navigate to a new page

Whenever I have an image displayed on my Nuxt page and then navigate away from it, the image breaks and I can't figure out why. This is what my code looks like: <img :src="baseUrl + 'storage/'+ front.featured_image" alt="p ...

Highlight dates in Vue.js that are overdue using a date filter

Currently, I have a Vue filter set up to display dates in a visually appealing way. However, I am looking to enhance the filter by adding a feature that would highlight dates in red if they are overdue (meaning the date is earlier than the current date). I ...

What is the name of the JavaScript code editor that includes line numbering for plain text?

Looking to incorporate a text area with line numbering features. I experimented with EditArea, but encountered difficulties when working with text files. While syntax highlighting for various programming languages would be a nice touch, my primary focus ...

Try using the slice method to cut a portion of a JSON object

I am trying to chop up a JSON array, but keep encountering the error message below: Object # has no method 'slice' This is my current code snippet: $scope.getPagedDataAsync = function (pageSize, page, searchText) { setTimeout(function ( ...

Slider for jQuery or Ajax framework

Currently, I am in search of a gauge that contains multiple concentric circles, with each circle displaying values of different entities, similar to the image provided. Each individual needle indicates the value of its corresponding entity. I have come a ...

Enhancing productivity with tools for developers and effortless tab navigation

During my development process, I always keep the developer tools open on one or more of my tabs. However, I noticed that when I switch to a tab where the developer tools were not previously open, a resize event is triggered. Strangely, this event causes el ...

Create a typescript class object

My journey with Typescript is just beginning as I delve into using it alongside Ionic. Coming from a background in Java, I'm finding the syntax and approach quite different and challenging. One area that's giving me trouble is creating new object ...

Achieving both positive and negative styling in AngularJS with ng-class: A guide

I'm currently working on an application that requires indicating red for negative values and blue for positive values in a calculation. <td class="amount debit"> <input type="text" class="form-control" ng-model="vm.model.form.amount_debi ...

Retrieve the current state of the toggle component by extracting its value from the HTML

I have a unique component that consists of a special switch and several other elements: <mat-slide-toggle (change)="toggle($event)" [checked]="false" attX="test"> ... </mat-slide-toggle> <p> ... </p> F ...

Displaying interactive charts in a pop-up window using Highcharts within a Bootstrap

I am looking to display a highchart inside a popover. Check out my code in this jsfiddle http://jsfiddle.net/hfiddle/abpvnys5/47/. Here is the HTML: <ul class="stat_list" style="float: left;"> <a data-toggle="popover" data-trigger="hover ...

The issue persists with the JavaScript window.location script constantly refreshing

I am currently working on a small web application where I want to update 2 parameters in the URL using Javascript. However, every time I use "window.location.search = 'scene.html?name=' + person + '&scene=' + readCookie("scene");", ...