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

Counting newlines in a variable length in AngularJS is not being considered

Whenever I input text and include new lines using test.length, the new lines are not counted within the string. Since I am utilizing this text for sending SMS messages where all newlines need to be accounted for, this is an issue. Any suggestions? Press e ...

Fill a dropdown menu with options from a JSON object, arranging them in ascending order

I have a JSON hash that I am using to populate a combo box with the following code: $.each(json_hash, function(key, value) { $("#select").append("<option value='" + key + "'>" + value + "</option>"); }); The functionality w ...

An issue has occurred with NPM CI where the bindings are not available from watchpack-chokidar2:fsevents

After executing npm ci on GitHub Actions, I encountered the following error: Run npm ci npm ERR! bindings not accessible from watchpack-chokidar2:fsevents npm ERR! A complete log of this run can be found in: npm ERR! /home/runner/.npm/_logs/2021-09-17 ...

Is it possible to transfer files using web-bluetooth technology?

As I work on developing an embedded system that counts the number of cars, saves their speed and time data in a logs file using rsyslog. Simultaneously, I am creating a web-API (in Typescript/Angular with Electron for Desktop usage and later Web as well) t ...

Adding custom styles to Material-UI components

` import React, { Component } from 'react'; import Header from './Components/UI/header'; import { Box, Paper } from '@material-ui/core'; import { ThemeProvider, withStyles} from '@material-ui/core/styles'; const ...

Is it possible to engage in peer-to-peer chatting using the Firebase Chat application on a web platform?

I'm currently utilizing a firebase chat application in conjunction with AngularJS. My specific need is for messages to be sent from one user to another user only, without being broadcasted to all users. Are there any methods or frameworks that allow f ...

Guidance on implementing fallback font formats using FontFace API

I am exploring the FontFace API (not @fontface) and wondering if there is an easy way to include multiple font formats, similar to providing multiple sources in @fontface. Alternatively, is there a simple method to identify which font formats are supporte ...

Is it possible to transform a .csv document into a JavaScript array with dictionaries? Each dictionary's keys would correspond to the column headers in the .csv file, and the values would be the

Let's imagine a scenario where I have a .csv file with the column headers listed in the first row, and their respective values are provided in the subsequent rows as shown below: index,id,description,component,service 0,5,lorem ipsum,7326985,Field Ser ...

Crop box overlaying video background

Utilizing jCrop to establish a crop region for a video element. My goal is to make the video section within the crop area fill a container with identical proportions, but I'm encountering challenges with the mathematical calculations. The sizes of th ...

Steps for dynamically loading the content of a Bootstrap 4 Modal

I am currently in the process of developing a website that will showcase a wide range of images. The design is set up as a landing page with all content contained within the main HTML page - there is only an index.html file for now. This website will serv ...

Tips for adding JSON values to an object

There is a specific object called SampleObject which has the following structure: { ID: "", Name: "", URL: "", prevName: "", Code: "", } I am looking to insert the values from the JSON object below (values only): var object = { "Sample ...

Nullify the unfulfilled fetch call

When a value is entered in the search bar on the webpage, it gets added to a URL and used to retrieve JSON data. Everything works smoothly, but if a value is inputted that the API doesn't have information for, a null response is returned. The questio ...

I'm having trouble executing the JavaScript function

function contentChange(){ var paragraphs = document.getElementsByTagName("p"); for(var i = 0 ; i < paragraphs.length ; i++){ paragraphs[i].innerHTML = "hello" ;}} contentChange(); I'm struggling to change the content of all ...

The custom tab component in React is currently not accepting the "disabledTabs" prop

I have designed a tab component as shown below: tab/index.jsx import React from 'react'; import TabHeader from './header'; import TabBody from './body'; import TabHeaderList from './header/list'; import TabBodyList ...

Arranging nested arrays

There is a nested list provided with the following markup (which cannot be altered currently). My goal is to sort this list and all nested lists by the title of the 'a' tag. The initial div (not nested in 'li') should be used for sortin ...

Setting up SSL/TLS certificates with Axios and Nest JS

I have a Nest JS application set up to send data from a local service to an online service. However, the requests are not working because we do not have an SSL certificate at the moment. Can anyone provide guidance on configuring Axios in Nest JS to accept ...

JavaScript code to determine if a Rating is enabled for a SharePoint Online list

Currently, I am working on a JavaScript code that will allow users to provide star ratings for specific articles through a widget. One of the requirements is to first verify if the Rating feature is enabled for a particular SharePoint list. If it is enable ...

jQuery's find method returns a null value

During my Ajax POST request, I encountered an issue where I wanted to replace the current div with the one received from a successful Ajax call: var dom; var target; $.ajax({ type: "POST", url: "http://127.0.0.1/participants", data: "actio ...

Could one potentially generate new static files in Nextjs without needing to rebuild the entire app?

After recently beginning to utilize NextJs' getStaticProps feature, I have found that the static files generated at build time are quite impressive. However, my content is not static and requires updates without having to rebuild the entire app each t ...

Leverage the power of effekt in your AngularJS development

Can anyone demonstrate how to implement animation effects with AngularJS? Has someone created an example using Effeckt.css? ...