How it works
- The user types at least 3 characters.
- After about 250 ms without typing, call the suggestion API.
- Show the first 5 suggestions; the user picks one.
- Store the address label and coordinates with the order.
Call the suggestion API
curl --get 'https://cloud.gmap.vn/api/idunn/v1/autocomplete' \
--header 'x-api-key: public-gmap-cloud-x-api-key-demo' \
--data-urlencode 'q=Chợ Hàn' \
--data 'lang=vi'Each suggestion is a GeoJSON Feature with properties.geocoding.label and geometry.coordinates, just like the search API.
Sample code
You need an input#address, a list ul#suggestions and two hidden fields #lat and #lon in your form.
const KEY = 'public-gmap-cloud-x-api-key-demo';
const input = document.querySelector('#address');
const list = document.querySelector('#suggestions');
let timer;
let controller;
input.addEventListener('input', () => {
clearTimeout(timer);
const q = input.value.trim();
if (q.length < 3) return list.replaceChildren();
timer = setTimeout(async () => {
controller?.abort();
controller = new AbortController();
const url = new URL('https://cloud.gmap.vn/api/idunn/v1/autocomplete');
url.search = new URLSearchParams({ q, lang: 'vi', 'x-api-key': KEY });
try {
const { features = [] } = await fetch(url, { signal: controller.signal }).then((r) => r.json());
list.replaceChildren(...features.slice(0, 5).map(toItem));
} catch (error) {
if (error.name !== 'AbortError') list.replaceChildren();
}
}, 250);
});
function toItem(feature) {
const item = document.createElement('li');
item.textContent = feature.properties.geocoding.label;
item.addEventListener('click', () => {
const [lon, lat] = feature.geometry.coordinates;
input.value = feature.properties.geocoding.label;
document.querySelector('#lat').value = lat;
document.querySelector('#lon').value = lon;
list.replaceChildren();
});
return item;
}For a better experience
- Waiting 250 ms and aborting stale requests (AbortController) cuts calls and stops old suggestions overwriting new ones.
- Let people choose with the arrow keys and Enter; use role="listbox" for the list.
- Always allow manual entry when the address is not suggested; never block checkout.
- Store both the display label and the coordinates; reverse-geocode later for the old (addr63) form if needed.
- Use your own API key for high-traffic pages; the demo key is for trials only.


