Search code examples
javascriptgoogle-mapsgoogle-maps-api-3google-api

How do I create Boundary Polygons using Data-driven Styling, after PlaceFeature.displayName has been deprecated? - JavaScript Google Maps API


I have a website that uses Google Maps API to create a map, with one random country being highlighted at a time. The way I currently highlight a country is using data-driven styling to create boundary polygons:

Example of how the map should look

But, Google recently started throwing errors, saying that the displayName property (which I use) could no longer be used as of February 2023. Here's a snippet of how my code looked before the change:

featureLayer.style = (options) => {
  if (options.feature["displayName"] == "Italy") {
    return featureStyleOptions;
  }
};

In the official explanation, the fetchPlace() function should just be used as a replacement, because the fetchPlace() function also returns the displayName.

But fetchPlace() can't be used in a synchronous function (it only returns promises), so I tried rewriting the code. In this attempt I used the .then() method, but now it doesn't apply the boundary polygons at all:

featureLayer.style = (options) => {
  options.feature.fetchPlace().then((Place) => {
    if (Place["displayName"] == "Italy") {
      return featureStyleOptions;
    }
  });
};

I only have limited knowledge of how promises/.then() work in JavaScript and how they handle the values, so I might be completely wrong with this approach.

Ideally I would just be using the PlaceId as a replacement for DisplayName, but I don't have any way of obtaining the IDs. I will appreciate any kind of help with this problem. Thank you!


Solution

  • displayName is deprecated but not the placeId.

    Below is an example highlighting Italy. To get the Place ID, you can use the Place ID finder. I have added a call to the Geocoder to be able to fit the map to the feature.

    let map;
    let featureLayer;
    
    function initMap() {
    
      let geocoder = new google.maps.Geocoder();
      map = new google.maps.Map(document.getElementById("map"), {
        center: {
          lat: 0,
          lng: 0
        },
        zoom: 13,
        mapId: "8ec1ff859561face", // You need to create your own map ID
      });
    
      featureLayer = map.getFeatureLayer("COUNTRY");
    
      // Define the styling options
      const featureStyleOptions = {
        strokeColor: "#00FF00",
        strokeOpacity: 1,
        strokeWeight: 1,
        fillColor: '#519400',
        fillOpacity: 1,
      };
    
      // Below Place ID is "Italy"
      let placeId = 'ChIJA9KNRIL-1BIRb15jJFz1LOI';
    
      geocoder.geocode({
          placeId: placeId
        })
        .then(({
          results
        }) => {
          map.fitBounds(results[0].geometry.viewport);
        })
        .catch((e) => {
          console.log('Geocoder failed due to: ' + e)
        });
    
      // Apply the style to a single boundary.
      featureLayer.style = (options) => {
        if (options.feature.placeId == placeId) {
          return featureStyleOptions;
        }
      };
    }
    #map {
      height: 180px;
    }
    <div id="map"></div>
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&v=beta" defer></script>

    Regarding fetchPlace(), the documentation states:

    Do not call this from a FeatureStyleFunction since only synchronous FeatureStyleFunctions are supported.