Luồng hoạt động
- Người dùng gõ ít nhất 3 ký tự.
- Sau khoảng 250 ms không gõ thêm, gọi API gợi ý.
- Hiện 5 gợi ý đầu; người dùng chọn một.
- Lưu nhãn địa chỉ và tọa độ vào đơn hàng.
Gọi API gợi ý
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'Mỗi gợi ý là một Feature GeoJSON với properties.geocoding.label và geometry.coordinates, giống API tìm kiếm.
Mã mẫu
Cần một ô input#address, danh sách ul#suggestions và hai ô ẩn #lat, #lon trong biểu mẫu.
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;
}Để trải nghiệm tốt hơn
- Chờ 250 ms và hủy yêu cầu cũ (AbortController) giúp giảm số lần gọi và tránh gợi ý cũ hiện đè lên gợi ý mới.
- Cho phép chọn gợi ý bằng phím mũi tên và Enter; dùng role="listbox" cho danh sách.
- Luôn cho người dùng tự nhập nếu không thấy địa chỉ của mình; đừng chặn thanh toán.
- Lưu cả nhãn hiển thị và tọa độ; khi cần, tra cứu ngược để có thêm cách ghi cũ (addr63).
- Ưu tiên khóa API riêng cho trang có lượng truy cập lớn; khóa demo chỉ để thử.


