Skip to main content

Address Search

|

This example demonstrates how to perform guided address searches and display the results on an interactive map.

Live Demo

Overview

This example shows how to:

  • Search for addresses hierarchically (country → city → street → house number)
  • Use the GuidedAddressSearchService for structured address lookup
  • Highlight and center the map on the found address
  • Display search progress messages

Code Implementation

Imports

First, import the required modules from the SDK:

import {
GemKit,
GemMap,
Landmark,
AddressDetailLevel,
GemError,
AnimationType,
GuidedAddressSearchService,
GemAnimation
} from '@magiclane/maps-sdk';

Setup UI and Map

Initialize the map and add a search button:

index.ts
window.addEventListener('DOMContentLoaded', async () => {
const gemKit = await GemKit.initialize(GEMKIT_TOKEN);
await PositionService.instance;

const container = document.getElementById('map-container');
if (!container) throw new Error('Map container not found');

const viewId = 1;
const wrapper = gemKit.createView(viewId, (gemMap: GemMap) => {
map = gemMap;
});
if (wrapper) container.appendChild(wrapper);

// Add search button
const searchBtn = document.createElement('button');
searchBtn.onclick = onSearchButtonPressed;
document.body.appendChild(searchBtn);
});

Address Search Helper

Create a reusable function to search for address components:

index.ts
function searchAddress({
landmark,
detailLevel,
text
}: {
landmark: Landmark;
detailLevel: AddressDetailLevel;
text: string;
}): Promise<Landmark | null> {
return new Promise((resolve) => {
GuidedAddressSearchService.search(
text,
landmark,
detailLevel,
(err: GemError, results: Landmark[]) => {
if (
(err !== GemError.success && err !== GemError.reducedResult) ||
!results ||
results.length === 0
) {
resolve(null);
} else {
resolve(results[0]);
}
}
);
});
}

Search through address hierarchy from country to house number:

index.ts
async function onSearchButtonPressed() {
showMessage('Search is in progress.');

// 1. Country: Spain
const countryLandmark = GuidedAddressSearchService.getCountryLevelItem('ESP');
if (!countryLandmark) {
return showMessage('Country not found.');
}
console.log('Country:', countryLandmark.name);

// 2. City: Barcelona
const cityLandmark = await searchAddress({
landmark: countryLandmark,
detailLevel: AddressDetailLevel.city,
text: 'Barcelona'
});
if (!cityLandmark) {
return showMessage('City not found.');
}
console.log('City:', cityLandmark.name);

// 3. Street: Carrer de Mallorca
const streetLandmark = await searchAddress({
landmark: cityLandmark,
detailLevel: AddressDetailLevel.street,
text: 'Carrer de Mallorca'
});
if (!streetLandmark) {
return showMessage('Street not found.');
}
console.log('Street:', streetLandmark.name);

// 4. House number: 401
const houseNumberLandmark = await searchAddress({
landmark: streetLandmark,
detailLevel: AddressDetailLevel.houseNumber,
text: '401'
});
if (!houseNumberLandmark) {
return showMessage('House number not found.');
}
console.log('House number:', houseNumberLandmark.name);

// Present the final result
presentLandmark(houseNumberLandmark);
showMessage('Search complete!');
}

Highlight and Center on Result

Display the found address on the map:

index.ts
function presentLandmark(landmark: Landmark) {
if (!map) return;

// Highlight the landmark on the map
map.activateHighlight([landmark]);

// Center the map with animation
const animation = new GemAnimation({ type: AnimationType.linear });
map.centerOnCoordinates(landmark.coordinates, {
zoomLevel: 50,
animation: animation
});
}

Utility Functions

Show temporary status messages:

function showMessage(message: string, duration = 3000) {
let msgDiv = document.getElementById('search-msg');
if (!msgDiv) {
msgDiv = document.createElement('div');
msgDiv.id = 'search-msg';
msgDiv.style.cssText = `
position: fixed; top: 20px; right: 20px; background: #333;
color: #fff; padding: 12px 20px; border-radius: 8px;
z-index: 2000; font-size: 1em;
`;
document.body.appendChild(msgDiv);
}
msgDiv.textContent = message;
setTimeout(() => {
msgDiv.textContent = '';
}, duration);
}

Key Features

The GuidedAddressSearchService enables hierarchical address lookup:

  1. Country Level: Start with getCountryLevelItem('ESP') for Spain
  2. City Level: Search within country with AddressDetailLevel.city
  3. Street Level: Search within city with AddressDetailLevel.street
  4. House Number: Find specific address with AddressDetailLevel.houseNumber

Address Detail Levels

The AddressDetailLevel enum defines search granularity:

  • country - Country-level search
  • city - City/town-level search
  • street - Street-level search
  • houseNumber - Specific house number

Error Handling

The search callback returns two possible success codes:

  • GemError.success - Full results returned
  • GemError.reducedResult - Partial/reduced results available

Both are considered valid responses. Any other error code indicates failure.

Map Presentation

When displaying the result:

  1. Activate Highlight: map.activateHighlight([landmark]) marks the location
  2. Center Map: map.centerOnCoordinates() with zoom level 50
  3. Animation: Use GemAnimation with AnimationType.linear for smooth transition

Implementation Details

  • Async/Await Pattern: Use Promises to handle async search callbacks
  • Early Returns: Exit search flow if any level fails to find results
  • Console Logging: Log each successful level for debugging
  • Status Messages: Show progress and completion messages to user
  • Country Codes: Use ISO 3166-1 alpha-3 codes (e.g., 'ESP' for Spain)

Use Cases

  • Complete Address Lookup: Find exact addresses from hierarchical components
  • Address Validation: Verify address existence through each level
  • Location Discovery: Guide users through address selection process
  • International Addressing: Search addresses in any supported country

Next Steps