Using Localities with the Map JS API

A comprehensive guide to using the Localities API (Autocomplete, Details, and Geocoding) through the Woosmap Map JS’s LocalitiesService.

  1. Overview
  2. Getting Started
  3. Localities Autocomplete and Details
  4. Geocoding and Reverse Geocoding
  5. Best Practices

Overview

The LocalitiesService class is the primary and recommended way to interact with the Woosmap Localities API directly from the Map JS API. It provides a straightforward, promise-based interface for the main Localities functionalities, including:

This guide covers how to use each of these features.

Getting Started

Before using the LocalitiesService, you must have a secure and valid Woosmap API key with the Localities API enabled.

Next, load the Map JS API library by including the following script tag in your HTML page, replacing YOUR_API_KEY with your key.

HTML
        <script async 
    src="https://sdk.woosmap.com/map/map.js?key=YOUR_API_KEY&callback=initMap">
</script>

    

For more details, see the Get Started with Map JS API guide.

Localities Autocomplete and Details

This feature allows you to implement a search box that provides address predictions as a user types and then retrieve full details for a selected prediction.

Localities Autocomplete Request

To begin, create an instance of woosmap.map.LocalitiesService and call the autocomplete() method, passing it a LocalitiesAutocompleteRequest object.

Type definition for LocalitiesAutocompleteRequest
        {
    input: string,
    components?: woosmap.map.localities.LocalitiesComponentRestrictions,
    customDescription?: string,
    data?: woosmap.map.localities.LocalitiesRequestData,
    extended?: string,
    language?: string,
    location?: woosmap.map.LatLng | woosmap.map.LatLngLiteral,
    radius?: number,
    types?: string | string[],
}

    

A typical request looks like this:

JavaScript
        const autocompleteRequest = {
    input: "10 downing street",
    types: ["locality", "address"],
    language: "EN",
    components: {country: ["GB"]},
};

const localitiesService = new woosmap.map.LocalitiesService();
localitiesService
    .autocomplete(autocompleteRequest)
    .then((response) => {
        // response.localities contains an array of predictions
        console.log(response.localities);
    })
    .catch((error) => console.error(error));

    

Localities Autocomplete Response

A successful autocomplete() call returns a promise that resolves with a LocalitiesAutocompleteResponse object, which contains an array of LocalitiesPredictions in the localities field. Each prediction contains a description and a unique public_id used to fetch more details.

Localities Details Request

To get full details for a selected prediction, use the getDetails() method, passing the public_id from the autocomplete response.

Type definition for LocalitiesDetailsRequest
        {
    publicId: string,
    language?: string,
    fields?: string,
    countryCodeFormat?: string,
}

    

Here is an example call:

JavaScript
        const detailsRequest = {
    publicId: "aGVyZTphZjpzdHJlZXRzZWN0aW9uOlpWN1NSWDhMUlNlRVpWU3hQMUhFREQ6Q2dnSUJDRHd5c25UQWhBQkdnSXhNQQ", // public_id for "10 Downing Street"
    language: "fr",
};

const localitiesService = new woosmap.map.LocalitiesService();
localitiesService
    .getDetails(detailsRequest)
    .then((response) => {
        // response.result contains the full address details
        console.log(response.result);
    })
    .catch((error) => console.error(error));

    

Localities Details Response

A successful getDetails() call returns a LocalitiesDetailsResponse object whose result field contains detailed information, including formatted_address, geometry, and address_components.


Geocoding and Reverse Geocoding

The geocode() method allows you to translate addresses into coordinates and vice-versa.

Request Localities Geocode

To make a request, call LocalitiesService.geocode() with a LocalitiesGeocodeRequest object. You must provide either an address for geocoding or a latLng for reverse geocoding.

Below is an example of a reverse geocoding request:

JavaScript
        const reverseGeocodeRequest = {
    latLng: {lat: 43.610, lng: 3.876},
    language: "fr",
    components: {country: ["FR"]},
};

const localitiesService = new woosmap.map.LocalitiesService();
localitiesService
    .geocode(reverseGeocodeRequest)
    .then((response) => {
        // response.results contains an array of matching addresses
        console.log(response.results);
    })
    .catch((error) => console.error(error));

    

To perform a forward geocoding request, simply provide an address string:

JavaScript
        const geocodeRequest = {
    address: "24 Rue de la Paix, Paris, France",
};
// ...then call localitiesService.geocode(geocodeRequest)

    

Localities Geocode Response

A successful geocode() call returns a LocalitiesGeocodeResponse object. Its results field contains an array of localities, each with the same structure as a LocalitiesDetailsResponse result, including formatted_address, geometry, and address_components.

Best Practices

Debouncing Autocomplete Requests

To manage API usage and prevent race conditions where responses return out of order, it is recommended to “debounce” your autocomplete requests. This ensures an API call is only made after the user has stopped typing for a brief period.

Here is a generic function to debounce any promise-based function:

Autocomplete Debounce Promise
        
type DebouncePromiseFunction<T, Args extends any[]> = (
  ...args: Args
) => Promise<T>;

function debouncePromise<T, Args extends any[]>(
  fn: (...args: Args) => Promise<T>,
  delay: number,
): DebouncePromiseFunction<T, Args> {
  let timeoutId: ReturnType<typeof setTimeout> | null = null;
  let latestResolve: ((value: T | PromiseLike<T>) => void) | null = null;
  let latestReject: ((reason?: any) => void) | null = null;

  return function (...args: Args): Promise<T> {
    return new Promise<T>((resolve, reject) => {
      if (timeoutId !== null) {
        clearTimeout(timeoutId);
      }
      latestResolve = resolve;
      latestReject = reject;
      timeoutId = setTimeout(() => {
        fn(...args)
          .then((result) => {
            if (latestResolve === resolve && latestReject === reject) {
              resolve(result);
            }
          })
          .catch((error) => {
            if (latestResolve === resolve && latestReject === reject) {
              reject(error);
            }
          });
      }, delay);
    });
  };
}


    
        function debouncePromise(fn, delay) {
  let timeoutId = null;
  let latestResolve = null;
  let latestReject = null;

  return function (...args) {
    return new Promise((resolve, reject) => {
      if (timeoutId !== null) {
        clearTimeout(timeoutId);
      }

      latestResolve = resolve;
      latestReject = reject;
      timeoutId = setTimeout(() => {
        fn(...args)
          .then((result) => {
            if (latestResolve === resolve && latestReject === reject) {
              resolve(result);
            }
          })
          .catch((error) => {
            if (latestResolve === resolve && latestReject === reject) {
              reject(error);
            }
          });
      }, delay);
    });
  };
}


    

You can then apply it to the autocomplete method:

JavaScript
        const localitiesService = new woosmap.map.LocalitiesService();

// Debounce autocomplete request for 200ms
const debouncedAutocomplete = debouncePromise(localitiesService.autocomplete, 200);

debouncedAutocomplete(autocompleteRequest)
    .then((response) => {
        console.log(response.localities);
    })
    .catch((error) => {
        if (error.name !== 'DebouncePromise') { // Ignore debounce cancellations
            console.error(error);
        }
    });

    
Was this article helpful?
Have more questions? Submit a request