How can markers be filtered on a Google Map API without the need to refresh the map?

I have created an Angular JS module that utilizes the Google Map API. The map is defined as a global variable, along with a global array for markers, and functions for managing these markers such as removing them, resetting the map, and adding new markers.

angular.module('gmapService', []).factory('gmapService', function($rootScope, $http){
    var googleMapService = {};

    var map;
    var markers = [];

function removeExistingMarkersFromTheMap() {
        for (var i = 0; i < markers.length; i++ ) {
            markers[i].setMap(null);
        }
        markers.length = 0;
}

var resetMap = function() {

        var oldZoom = map.zoom;
        var oldCenter = map.center;

        map = new google.maps.Map(document.getElementById('map'), {
            zoom: oldZoom,
            center: oldCenter
        });

        removeExistingMarkersFromTheMap();
    }

googleMapService.placeMarkersOnMap = function(map, markersToPut) {
    // querying the data needed to place markers on the map
    for(var i=0; i<data.length; i++) {
        var marker = new google.maps.Marker({
                    position: latLng,
                    icon: icon
                    });
            markers.push(marker);
        }

        var mcOptions = {gridSize: 60, minZoom: 4, maxZoom: 12};
        var mc = new MarkerClusterer(map, markers, mcOptions);
    }
return googleMapService;
}

Currently, my process involves calling resetMap(), followed by placeMarkersOnMap(). This approach works fine, but I am seeking a way to update the displayed data on the map without having to reload the entire map itself.

Unfortunately, when I only execute removeExistingMarkersFromTheMap() and then placeMarkersOnMap(), the old data still persists. What could be causing this issue?

Answer №1

Utilizing the MarkerClusterer class for displaying markers, removing existing markers from the map using the previous method is no longer valid:

for (var i = 0; i < markers.length; i++ ) {
    markers[i].setMap(null);
}
markers.length = 0;

A better approach would be to use the clearMarkers function, which does the following:

Clears all clusters and markers from the clusterer

Furthermore, instead of instantiating a map object in a service, it is recommended to assign this task to a controller or directive.

Below is a modified version for the gmapService service:

angular.module('gmapService', []).factory('gmapService', function ($rootScope, $http) {
    var googleMapService = {};


    var markerCluster;

    googleMapService.removeExistingMarkersFromTheMap = function () {
        if (!markerCluster) return;
        markerCluster.clearMarkers();
    }


    googleMapService.placeMarkersOnMap = function (map, data) {
        var markers = [];

        this.removeExistingMarkersFromTheMap(); //ensure first that existing markers have been removed
        for (var i = 0; i < data.length; i++) {
            var marker = new google.maps.Marker({
                position: new google.maps.LatLng(data[i].lat,data[i].lng),
                //icon: icon
            });
            markers.push(marker);
        }

        var mcOptions = { gridSize: 60, minZoom: 4, maxZoom: 12 };
        markerCluster = new MarkerClusterer(map, markers, mcOptions);
    }
    return googleMapService;
});

Working example

angular.module('gmapService', []).factory('gmapService', function ($rootScope, $http) {
    var googleMapService = {};

    
    var markerCluster;

    googleMapService.removeExistingMarkersFromTheMap = function () {
        if (!markerCluster) return;
        markerCluster.clearMarkers();
    }


    googleMapService.placeMarkersOnMap = function (map, data) {
        var markers = [];

        this.removeExistingMarkersFromTheMap(); //ensure first that existing markers have been removed
        for (var i = 0; i < data.length; i++) {
            var marker = new google.maps.Marker({
                position: new google.maps.LatLng(data[i].lat,data[i].lng),
                //icon: icon
            });
            markers.push(marker);
        }

        var mcOptions = { gridSize: 60, minZoom: 4, maxZoom: 12 };
        markerCluster = new MarkerClusterer(map, markers, mcOptions);
    }
    return googleMapService;
});

var app = angular.module('mapApp', ['gmapService']);

app.controller('mapCtrl', function ($scope, gmapService) {
    $scope.locations = [
            { Id: 1, name: 'Oslo', lat: 59.923043, lng: 10.752839 },
            { Id: 2, name: 'Stockholm', lat: 59.339025, lng: 18.065818 },
            { Id: 3, name: 'Copenhagen', lat: 55.675507, lng: 12.574227 },
            { Id: 4, name: 'Berlin', lat: 52.521248, lng: 13.399038 },
            { Id: 5, name: 'Paris', lat: 48.856127, lng: 2.346525 }
    ];

    $scope.initMap = function () {
        $scope.map = new google.maps.Map(document.getElementById('map'), {
            center: { lat: 59.339025, lng: 18.065818 },
            zoom: 4
        });

        var btnAdd = document.getElementById('btnAdd');
        $scope.map.controls[google.maps.ControlPosition.TOP_LEFT].push(btnAdd);
        var btnRemove = document.getElementById('btnRemove');
        $scope.map.controls[google.maps.ControlPosition.TOP_LEFT].push(btnRemove);


        $scope.addMarkers = function () {
            gmapService.placeMarkersOnMap($scope.map, $scope.locations);
        };

        $scope.removeMarkers = function () {
            gmapService.removeExistingMarkersFromTheMap();
        };
    };

   
    $scope.initMap();
});
html, body {
    height: 400px;
    margin: 0;
    padding: 0;
}

#map {
    height: 400px;
}
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://rawgit.com/googlemaps/js-marker-clusterer/gh-pages/src/markerclusterer.js"></script> 
<div ng-app="mapApp" ng-controller="mapCtrl">
        <button id="btnAdd" ng-click="addMarkers()">Add markers</button>
        <button id="btnRemove" ng-click="removeMarkers()">Remove markers</button>
        <div id="map"></div>
 </div>

Demo on Codepen

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

Encountering a CORS Policy Blockage Issue When Using JSON Data, but Resolving it by Changing the Header Type

I created a basic input form that updates data when information is added to it. After following a tutorial, I noticed they used application/json in the header for rendering json data within the input fields. let url = 'http://local ...

Recursion using Node.js Promises

I'm facing some difficulties while iterating through my Promises and completing my parser code: let startFrom = 0, totalRecords = 10000, doneRecords = 0 const rows = 10 const parserRequests = function () { if (startFrom <= totalRecords) { ...

Decompressing JSON data type document

I am currently facing an issue with deserializing a Json string to a custom class. Here is the structure of my json data: externDossierNr:"foo10" internDossierNr:"2016010" rapport:File testarray:Array[3] testword:42 __proto__:Object The fields externDoss ...

Error in Firefox when converting a string to a date in JavaScript using the format mm-dd-yyyy

Hi, I am encountering an issue with converting a string in the format mm-dd-yyyy into a date object. While it works perfectly fine in Internet Explorer and Chrome, it does not work in Firefox as it returns an invalid date at times. I have also tried using ...

Unlock hidden content with a single click using jQuery's click event

I have a question that seems simple, but I can't quite get the syntax right. My issue is with a group of stacked images. When I click on an image, I want it to move to the front and display the correct description above it. Currently, clicking on the ...

Node.js - Synchronize asynchronous calls to ensure coordinated execution in code

I am trying to figure out how to make a for loop with an async function wait until all the async functions called within it are finished before allowing the code to continue. In my scenario, I have a variable "bar" that contains a JSON array with other ne ...

Issue with the execution of Javascript code. Edit required

After creating a registration form that allows users to input their information for registration, I encountered an issue where if certain fields were left empty or if the user name was unavailable or the email address was already registered, a warning mess ...

Express server consistently receives JSON requests that contain no data in the request body

Currently, I am in the process of developing a small server and website using Express. At this point, my goal is to send a POST request to my Express server with basic credentials encoded as JSON. The issue I am facing is that no matter what I attempt, th ...

Angular 4's Panel Window: A User-Friendly Interface

Having experience with Adobe Flex, I am familiar with creating new panel windows in Action Script by using the 'new' keyword and popping them up using popups. The customization of these windows was achieved through functions provided in the Panel ...

When attempting to delete, I encounter an error stating that $index is undefined

I am currently working on a project that involves Angular and PHP. I have encountered an issue while trying to delete some information, even though the function seems to be retrieving the data correctly. I'm puzzled as to why it is not working as expe ...

Exploring the resolution of unit test for an Angular Bootstrap modal using the John Papa ViewModel style

A custom ModalService has been created to display two different types of dialogs, CancelDialog and ErrorDialog, based on the parameter passed to the service. For example, the following code will show an ErrorDialog: ModalService.openModal('Analysis ...

Transitioning from a multipage application to Piral: A comprehensive guide

Our organization operates several ASP.NET Core applications that are traditional multipage applications. As we develop a new portal using Piral, we want to incorporate elements from our existing applications while also introducing new modules. How can we ...

Problems arise with identification of asynchronous functions

My async functions have been used successfully in various projects, but when incorporating them into a new project, they suddenly stopped working. One of the functions causing trouble is: const ddbGet = async (params) => { try { const data ...

Vue component fails to render due to a simple issue

I've been diving into Vue.JS and I'm facing an issue where the component I created isn't showing up on the page. Here's a snippet of my component: import Vue from 'vue' const card = new Vue({ el: '#card', data: ...

Just for laughs: "The react-redux context value seems to be playing hide and seek; make sure to wrap the component in a <Provider> for it to show up!"

I encountered an issue while attempting to run a basic Jest test on a form React component: ● <LoginForm /> › clicking the validate button › should display page title ...

Obtaining zip files using AngularJS

Upon entering the following URL in my browser, I am prompted to download a file: My goal is to download this file using an AngularJS HTTP request. I have created a factory for this purpose, but unfortunately, the download is not successful. Even though ...

Tips for successfully implementing a basic JQuery code in Internet Explorer

Having trouble getting this to work on my website, especially in Internet Explorer. Check it out here: http://jsfiddle.net/b43hj/24/ Any tips on how to make it compatible with all browsers? Thank you edit - I've only used the code from the jsfidd ...

Effortlessly add and manipulate multiple classes in a generic class using querySelectorAll and classList, eliminating the

I'm encountering an issue that requires me to repeatedly utilize querySelectorAll with Element.classList. Each time, I must convert the NodeList obtained from Element.querySelectorAll into an Array. Then, I need to iterate over the Array using a for ...

What steps should I take to design and implement this basic search form?

Essentially, I have a three-page setup: - One page containing all possible search results such as: 'search result 1' 'search result 2' 'search result 3' - Another page with a search form and enter button. - And finally, a res ...

What is the process for generating an array of objects using JavaScript?

I am struggling to create an array of objects using JavaScript and facing errors with new lines added where I need to split the messages and collect row numbers. The row numbers should be comma-separated if it is a repetitive error message. I found a solu ...