Search code examples
google-mapsinfowindow

Cannot close infowindows in Google Maps. Error: Uncaught TypeError: Cannot read property 'close' of undefined


I am trying to create markers in my google map for the different properties that i have in my Node.js web app. I have been successful to do so but my infowindows do not close when clicked on the map. Below is my code and the error.

<% properties.forEach(function(location){ %>
  var loc = {lat: <%=location.lat %>, lng:<%= location.lng %>};

  var contentString = `
  <strong><%= location.name %><br />
  <%= location.location %></strong>
  <p><%= location.description %></p>
  `

  var marker = new google.maps.Marker({
    position: loc,
    map: map
  });

  marker['infowindow'] = new google.maps.InfoWindow({
    content: contentString
  });

       google.maps.event.addListener(marker, 'click', function() {
            // this['infowindow'].open(map, this);

           if(this.open){
            this['infowindow'].close();
            this.open = false;
        }
        else{
            this['infowindow'].open(map,this);
            this.open = true;
        }
        google.maps.event.addListener(map, 'click', function() {
            this['infowindow'].close();
            this.open = false;
        });

    });

  <% }); %>

and the error i get on the console is

Uncaught TypeError: Cannot read property 'close' of undefined


Solution

  • Comments:

    1. you are adding a map click listener for each marker (you only need one)
    2. the this inside the map click listener will be the map, not a marker.

    Suggestions:

    1. keep references to the markers as you create them (so you can iterate through them and close the infowindows when the map is clicked)
    2. only create one map click listener outside of your marker creation loop, close any open infowindows in that.
    var markers = [];  // create markers array to keep references to the markers
    
    <% properties.forEach(function(location){ %>
      var loc = {lat: <%=location.lat %>, lng:<%= location.lng %>};
    
      var contentString = '
      <strong><%= location.name %><br />
      <%= location.location %></strong>
      <p><%= location.description %></p>
      '
      var marker = new google.maps.Marker({
        position: loc,
        map: map
      });
    
      markers.push(marker);  // add each created marker to the array
    
      marker['infowindow'] = new google.maps.InfoWindow({
        content: contentString
      });
    
      google.maps.event.addListener(marker, 'click', function() {
        if(this.open){
          this['infowindow'].close();
          this.open = false;
        }
        else{
          this['infowindow'].open(map,this);
          this.open = true;
        }
      });
    
      <% }); %>
      // when the map is clicked, close any open infowindows
      google.maps.event.addListener(map, 'click', function() {
        for (var i = 0; i < markers.length; i++) {
          markers[i]['infowindow'].close();
          markers[i].open = false;
        }
      });
    

    proof of concept fiddle

    code snippet:

    // This example displays a marker at the center of Australia.
    // When the user clicks the marker, an info window opens.
    
    function initMap() {
      var uluru = {
        lat: -25.363,
        lng: 131.044
      };
      var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 4,
        center: uluru
      });
      var markers = [];
      // <% properties.forEach(function(location){ %>
      var loc = {
        lat: -25.363,
        lng: 131.044
      };
    
      var contentString = '<strong>name<br />location</strong><p>description</p>';
    
      var marker = new google.maps.Marker({
        position: loc,
        map: map
      });
      markers.push(marker);
      marker['infowindow'] = new google.maps.InfoWindow({
        content: contentString
      });
    
      google.maps.event.addListener(marker, 'click', function() {
        // this['infowindow'].open(map, this);
    
        if (this.open) {
          this['infowindow'].close();
          this.open = false;
        } else {
          this['infowindow'].open(map, this);
          this.open = true;
        }
      });
    
      // ============ 2 ============
      // 30.0002° S, 136.2092° E
      var loc = {
        lat: -30,
        lng: 136.2092
      };
    
      var contentString = '<strong>name 2<br />location 2</strong><p>description 2</p>';
    
      var marker = new google.maps.Marker({
        position: loc,
        map: map
      });
      markers.push(marker);
      marker['infowindow'] = new google.maps.InfoWindow({
        content: contentString
      });
    
      google.maps.event.addListener(marker, 'click', function() {
        // this['infowindow'].open(map, this);
    
        if (this.open) {
          this['infowindow'].close();
          this.open = false;
        } else {
          this['infowindow'].open(map, this);
          this.open = true;
        }
      });
    
      // <% }); %>
      google.maps.event.addListener(map, 'click', function() {
        for (var i = 0; i < markers.length; i++) {
    
          markers[i]['infowindow'].close();
          markers[i].open = false;
        }
      });
    }
    html,
    body,
    #map {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    <div id="map"></div>
    <!-- Replace the value of the key parameter with your own API key. -->
    <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap"></script>