Handle click events

Overview

You can make a feature layer respond to user click events, to get the place ID, display name, and feature type for the boundary that was clicked. The following example map shows the boundaries for Administrative Area Level 2, and shows an event handler that styles the clicked polygon, and displays an info window with the event data.

Enable feature layer events

Take the following steps to enable events on a feature layer:

  1. Register a feature layer for click event notifications by calling addListener(), passing the type of event (click) and the name of the event handler function.

    TypeScript

    // Add the feature layer.
    //@ts-ignore
    featureLayer = map.getFeatureLayer('ADMINISTRATIVE_AREA_LEVEL_2');
    // Add the event listener for the feature layer.
    featureLayer.addListener('click', handlePlaceClick);

    JavaScript

    // Add the feature layer.
    //@ts-ignore
    featureLayer = map.getFeatureLayer("ADMINISTRATIVE_AREA_LEVEL_2");
    // Add the event listener for the feature layer.
    featureLayer.addListener("click", handlePlaceClick);

  2. Apply a fill style with fillOpacity of 0.1 or greater to make a feature respond to events. Only visible features are clickable.

    TypeScript

    // Stroke and fill with minimum opacity value.
    //@ts-ignore
    const styleDefault: google.maps.FeatureStyleOptions = {
        strokeColor: '#810FCB',
        strokeOpacity: 1.0,
        strokeWeight: 2.0,
        fillColor: 'white',
        fillOpacity: 0.1 // Polygons must be visible to receive click events.
    };
    
    // Style for the clicked Administrative Area Level 2 polygon.
    //@ts-ignore
    const styleClicked: google.maps.FeatureStyleOptions = {
        ...styleDefault,
        fillColor: '#810FCB',
        fillOpacity: 0.5
    };

    JavaScript

    // Stroke and fill with minimum opacity value.
    //@ts-ignore
    const styleDefault = {
      strokeColor: "#810FCB",
      strokeOpacity: 1.0,
      strokeWeight: 2.0,
      fillColor: "white",
      fillOpacity: 0.1, // Polygons must be visible to receive click events.
    };
    // Style for the clicked Administrative Area Level 2 polygon.
    //@ts-ignore
    const styleClicked = {
      ...styleDefault,
      fillColor: "#810FCB",
      fillOpacity: 0.5,
    };
    

  3. Add code to handle the event. In this example, the event handler styles the selected polygon, and displays an info window.

    TypeScript

    // Handle the click event.
    async function handlePlaceClick(event) {
        let feature = event.features[0];
        if (!feature.placeId) return;
        // Apply the style to the feature layer.
        applyStyleToSelected(feature.placeId);
        // Add the info window.
        const place = await feature.fetchPlace();
        let content = '<span style="font-size:small">Display name: ' + place.displayName +
            '<br/> Place ID: ' + feature.placeId +
            '<br/> Feature type: ' + feature.featureType +
            '</span>';
        updateInfoWindow(content, event.latLng);
    }

    JavaScript

    // Handle the click event.
    async function handlePlaceClick(event) {
      let feature = event.features[0];
    
      if (!feature.placeId) return;
    
      // Apply the style to the feature layer.
      applyStyleToSelected(feature.placeId);
    
      // Add the info window.
      const place = await feature.fetchPlace();
      let content =
        '<span style="font-size:small">Display name: ' +
        place.displayName +
        "<br/> Place ID: " +
        feature.placeId +
        "<br/> Feature type: " +
        feature.featureType +
        "</span>";
    
      updateInfoWindow(content, event.latLng);
    }
    

Complete example code

TypeScript

let map: google.maps.Map;
let featureLayer;
let infoWindow: google.maps.InfoWindow;
async function initMap() {
    // Request needed libraries.
    const { Map, InfoWindow } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;

    map = new Map(document.getElementById('map') as HTMLElement, {
        center: { lat: 39.23, lng: -105.73 }, // Park County, CO 
        zoom: 8,
        // In the cloud console, configure this Map ID with a style that enables the
        // "Administrative Area Level 2" Data Driven Styling type.
        mapId: 'a3efe1c035bad51b', // <YOUR_MAP_ID_HERE>,
    });
    // Add the feature layer.
    //@ts-ignore
    featureLayer = map.getFeatureLayer('ADMINISTRATIVE_AREA_LEVEL_2');
    // Add the event listener for the feature layer.
    featureLayer.addListener('click', handlePlaceClick);
    infoWindow = new InfoWindow({});
    // Apply style on load, to enable clicking.
    applyStyleToSelected();
}
// Handle the click event.
async function handlePlaceClick(event) {
    let feature = event.features[0];
    if (!feature.placeId) return;
    // Apply the style to the feature layer.
    applyStyleToSelected(feature.placeId);
    // Add the info window.
    const place = await feature.fetchPlace();
    let content = '<span style="font-size:small">Display name: ' + place.displayName +
        '<br/> Place ID: ' + feature.placeId +
        '<br/> Feature type: ' + feature.featureType +
        '</span>';
    updateInfoWindow(content, event.latLng);
}
// Stroke and fill with minimum opacity value.
//@ts-ignore
const styleDefault: google.maps.FeatureStyleOptions = {
    strokeColor: '#810FCB',
    strokeOpacity: 1.0,
    strokeWeight: 2.0,
    fillColor: 'white',
    fillOpacity: 0.1 // Polygons must be visible to receive click events.
};

// Style for the clicked Administrative Area Level 2 polygon.
//@ts-ignore
const styleClicked: google.maps.FeatureStyleOptions = {
    ...styleDefault,
    fillColor: '#810FCB',
    fillOpacity: 0.5
};
// Apply styles to the map.
function applyStyleToSelected(placeid?) {
    // Apply styles to the feature layer.
    featureLayer.style = (options) => {
        // Style fill and stroke for a polygon.
        if (placeid && options.feature.placeId == placeid) {
            return styleClicked;
        }
        // Style only the stroke for the entire feature type.
        return styleDefault;
    };
}
// Helper function to create an info window.
function updateInfoWindow(content, center) {
    infoWindow.setContent(content);
    infoWindow.setPosition(center);
    infoWindow.open({
        map,
        shouldFocus: false,
    });
}

initMap();

JavaScript

let map;
let featureLayer;
let infoWindow;

async function initMap() {
  // Request needed libraries.
  const { Map, InfoWindow } = await google.maps.importLibrary("maps");

  map = new Map(document.getElementById("map"), {
    center: { lat: 39.23, lng: -105.73 },
    zoom: 8,
    // In the cloud console, configure this Map ID with a style that enables the
    // "Administrative Area Level 2" Data Driven Styling type.
    mapId: "a3efe1c035bad51b", // <YOUR_MAP_ID_HERE>,
  });
  // Add the feature layer.
  //@ts-ignore
  featureLayer = map.getFeatureLayer("ADMINISTRATIVE_AREA_LEVEL_2");
  // Add the event listener for the feature layer.
  featureLayer.addListener("click", handlePlaceClick);
  infoWindow = new InfoWindow({});
  // Apply style on load, to enable clicking.
  applyStyleToSelected();
}

// Handle the click event.
async function handlePlaceClick(event) {
  let feature = event.features[0];

  if (!feature.placeId) return;

  // Apply the style to the feature layer.
  applyStyleToSelected(feature.placeId);

  // Add the info window.
  const place = await feature.fetchPlace();
  let content =
    '<span style="font-size:small">Display name: ' +
    place.displayName +
    "<br/> Place ID: " +
    feature.placeId +
    "<br/> Feature type: " +
    feature.featureType +
    "</span>";

  updateInfoWindow(content, event.latLng);
}

// Stroke and fill with minimum opacity value.
//@ts-ignore
const styleDefault = {
  strokeColor: "#810FCB",
  strokeOpacity: 1.0,
  strokeWeight: 2.0,
  fillColor: "white",
  fillOpacity: 0.1, // Polygons must be visible to receive click events.
};
// Style for the clicked Administrative Area Level 2 polygon.
//@ts-ignore
const styleClicked = {
  ...styleDefault,
  fillColor: "#810FCB",
  fillOpacity: 0.5,
};

// Apply styles to the map.
function applyStyleToSelected(placeid) {
  // Apply styles to the feature layer.
  featureLayer.style = (options) => {
    // Style fill and stroke for a polygon.
    if (placeid && options.feature.placeId == placeid) {
      return styleClicked;
    }
    // Style only the stroke for the entire feature type.
    return styleDefault;
  };
}

// Helper function to create an info window.
function updateInfoWindow(content, center) {
  infoWindow.setContent(content);
  infoWindow.setPosition(center);
  infoWindow.open({
    map,
    shouldFocus: false,
  });
}

initMap();

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
  height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

HTML

<html>
  <head>
    <title>Handle Region Boundary Click Event</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map"></div>

    <!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "beta"});</script>
  </body>
</html>

Try Sample

Learn more about events