Source: https://developers.woosmap.com/products/map-api/services/localities-autocomplete-details/

> For clean Markdown of any page, append `.md` to the page URL.

> For a complete documentation index, see https://developers.woosmap.com/llms.txt

# Work with Localities



## Overview

The [`LocalitiesService class`](/products/map-api/reference/1.4/#woosmap.map.LocalitiesService) provides methods for using the Localities API through Woosmap Map JavaScript API. It supports modern usage patterns such as [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises).

This guide focus on the following supported operations from Localities:

- [Localities Autocomplete](/products/localities/features/autocomplete/) lets you search for addresses data using text query.
- [Localities Details](/products/localities/features/details/) provides details of an autocompleted address.

Review the example below to understand how to use autocomplete and get addresses details from Localities API using through Woosmap Map JS API:

https://demo.woosmap.com/js-samples/samples/localities-autocomplete/app/dist/
[](https://demo.woosmap.com/js-samples/samples/localities-autocomplete/highlight/highlight.html "Open in new tab with highlighted code")
Try sample 

- [CodeSandbox](https://codesandbox.io/p/devbox/github/woosmap/js-samples/tree/master/dist/samples/localities-autocomplete/app?file=index.ts)
- [JsFiddle](https://jsfiddle.net/gh/get/library/pure/woosmap/js-samples/tree/master/dist/samples/localities-autocomplete/jsfiddle)
- [Clone on Github](https://github.com/Woosmap/js-samples/tree/sample/localities-autocomplete)

## Getting started

Before using the Localities service in the Map JavaScript API, it is required to have a [secure and valid Woosmap API key](/api-reference/authentication/) and enable the Localities API for it.

Next, you must load the Map JS API library by including a script tag in your HTML page as follows:

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

See the [Get Started with Map JS API](/products/map-api/get-started/) guide for more information.

## Localities Autocomplete

You can call this endpoint by first creating a new instance of the [`woosmap.map.LocalitiesService`](/products/map-api/reference/1.4/#woosmap.map.LocalitiesService) class and then call the dedicated method.

### Localities Autocomplete Request

To initiate a request to Localities Autocomplete in the Woosmap Map JS API, create an object of type `woosmap.map.LocalitiesService` and call `LocalitiesService.autocomplete()`,passing it a [`LocalitiesAutocompleteRequest`](/products/map-api/reference/1.4/#woosmap.map.localities.LocalitiesAutocompleteRequest) object literal.

The `LocalitiesAutocompletesRequest` object literal contains the following fields:

```plaintext
{
    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[],
}
```

The fields are:

- `input` specifies the user entered input string.
- `components` (optional) used to filter over countries. Countries must be passed as an ISO 3166-1 Alpha-2 or Alpha-3 compatible country code.
- `customDescription` (optional) specifies the description format for all or some of the suggestion types selected.
- `data` (optional) opens suggestions to worldwide postal codes in addition to postal codes for Western Europe.
- `extended` (optional) allows a refined search over locality names that bears the same postal code. possible value is `extended=postal_code`
- `language`(optional) specifies the language code, using ISO 3166-1 Alpha-2 country codes, indicating in which language the results should be returned, if possible. If language is not supplied, the Localities service will use english as default language. No language necessary for postal\_code request.
- `location` (optional) specifies the location for prediction biasing. The location defines the point around which to retrieve predictions in priority.
- `radius` (optional) specifies the distance (in meters) within which to return place results. The maximum allowed radius is 100 000 meters. The default radius is 100 000 meters.
- `types` (optional) specifies the types of predictions to be returned. By default, suggestions return types `locality` and `postal_code`. can be either a single type or a list of `LocalitiesType`

Below is a sample `LocalitiesAutocompletesRequest`:

```javascript
const autocompleteRequest = {
  input: "10 downing street",
  types: ["locality", "address"],
  language: "EN",
  components: { country: ["GB"] },
  customDescription: "name,admin_1,admin_0",
  radius: 500000,
  location: { lat: 51.5007, lng: -0.1246 },
};
```

The `LocalitiesService`’s `autocomplete()` method is asynchronous and returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) object that is either fulfilled with an array of [`LocalitiesPredictions`](/products/map-api/reference/1.4/#woosmap.map.localities.LocalitiesPredictions) objects or rejected with an `APIError` object. You can attach handlers to this Promise object to process results upon operation success or failure.

```javascript
const localitiesService = new woosmap.map.LocalitiesService();
localitiesService
  .autocomplete(autocompleteRequest)
  .then((response) => {
    console.log(response.result);
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("done");
  });
```

### Localities Autocomplete Response

A successful `autocomplete()` call returns a `LocalitiesAutocompleteResponse` object with a `localities[]` field, which is an array of `LocalitiesPredictions` objects.

Each `LocalitiesPredictions` object may contain the following fields:

```plaintext
{
    localities[]: {
      description: string,
      public_id: string,
      type?: string,
      matched_substrings[]?: {
        description[]:{
          offset: number,
          length: number
        }
      },
      has_addresses?: boolean,
    }
}
```

- `description`: A combination of `name`, `admin_1`, `admin_0` or requested customDescription. The content varies based on the requested type.
- `public_id`: A unique identifier for the locality. To retrieve information about the locality, pass this identifier in the [Localities Details](#localities-details) request.
- `has_addresses` (optional): A boolean indicating if the postal code has addresses. This field is only returned for the `postal_code` type in the United Kingdom.
- `matched_substrings` (optional): An array of matched substrings for each field that matches elements in the input. Useful for highlighting these substrings.
- `type` (optional): The type of the prediction, such as `locality`, `address`, or `postal_code`.

## Localities Details

### Localities Details Request

The `getDetails()` method from `woosmap.map.LocalitiesService` is used to get details of a selected locality. It also returns a Promise object that resolves to a `LocalitiesDetailsResponse` object.

The `LocalitiesDetailsRequest` object literal contains the following fields:

```plaintext
{
    publicId: string,
    language?: string,
    fields?: string,
    countryCodeFormat?: string,
}
```

- `publicId`: A textual identifier that uniquely identifies a locality, returned from a `LocalitiesService.autocomplete()`.
- `language` (optional): The language code, using ISO 3166-1 Alpha-2 country codes, indicating in which language the results should be returned, if possible. If language is not supplied, the Localities service will use english as default language. No language necessary for postal\_code request.
- `fields` (optional): Used to limit the returning fields when `type=address`. by default, and for other types localities, all fields are return. Only one field is available: `geometry`.
- `countryCodeFormat` (optional): To specify the format for the short country code expected to be returned in the `address_components` field. Default is the format used to specify components or alpha2 if no components are specified.

Below is a sample call to `LocalitiesServices.getDetails()` method passing the resulted `publicId` from the above call to `LocalitiesServices.autocomplete()` (“10 Downing Street”).

```javascript
const detailsRequest = {
  publicId: "aGVyZTphZjpzdHJlZXRzZWN0aW9uOlpWN1NSWDhMUlNlRVpWU3hQMUhFREQ6Q2dnSUJDRHd5c25UQWhBQkdnSXhNQQ",
  language: "fr",
};
const localitiesService = new woosmap.map.LocalitiesService();
localitiesService
  .getDetails(detailsRequest)
  .then((response) => {
    console.log(response.result);
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("done");
  });
```

### Localities Details Response

A successful `getDetails()` call returns a `LocalitiesDetailsResponse` object with a `result` field, which may contain the following fields:

```plaintext
{
    result: {
      formatted_address: string,
      public_id: string,
      types[]:  woosmap.map.localities.LocalitiesTypes,
      geometry[]?: {
        accuracy: woosmap.map.localities.LocalitiesDetailsAccuracy,
        location: woosmap.map.LatLngLiteral,
        viewport: woosmap.map.LatLngBoundsLiteral,
      },
      name?: string,
      status?: string,
      address_components[]?: {
        long_name: string,
        short_name: string,
        types[]: string,
      },
    }
}
```

- `formatted_address`: Contains the readable text description of the result.
- `public_id`: Contains a unique ID for the detailed locality.
- `types`: Available locality types, represented as an array of LocalitiesTypes.
- `geometry`: The location of the result, in latitude and longitude, eventually associated with a Viewport. Accuracy is also provided for locality of type `address`.
- `name`: The postal code name if locality is of type postal\_code.
- `status`: This optional field is only available for UK addresses referenced as `not_yet_built`.
- `address_components`: An array containing Address Components with additional information.

## Debouncing Autocomplete Promise

Autocomplete is designed to support real-time, as-you-type search, processing requests for each keystroke to deliver instantaneous feedback. However, there are situations where the continuous as-you-type functionality may lead to unwanted behaviors.

- If you want control over search operations usage, you may prefer to wait until the user stops typing before triggering an autocomplete request. Similarly, as Localities is a rate-limited services, sending too many requests from a lot of users in a short time can lead to API errors. In such cases, debouncing your sources with waiting time can help limit the number of requests triggered by Autocomplete.

- If a later call takes less time than a previous one, it could potentially resolve before the previous one, leading to out-of-order execution. This is a common issue with asynchronous operations like promises.

To handle this, you can debounce your promise and implement a mechanism to ignore the results of all previous promises when a new one is created.

```typescript
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);
    });
  };
}
```

```javascript
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);
    });
  };
}
```

Finally, you can use this `debouncePromise()` function to debounce autocomplete request as follows:

```javascript
const localitiesService = new woosmap.map.LocalitiesService();
// Debounce autocomplete request for 10ms
const debouncedLocalitiesAutocomplete = debouncePromise(localitiesService.autocomplete, 10);
debouncedLocalitiesAutocomplete(autocompleteRequest)
  .then((response) => {
    console.log(response.result);
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
    console.log("done");
  });
```
