9.5 KiB
9.5 KiB
Leaflet Map Picker - Dokumentasi
Komponen reusable untuk memilih lokasi menggunakan Leaflet Maps dengan fitur pencarian dan reverse geocoding.
Fitur
- 🗺️ Interactive map dengan OpenStreetMap
- 🔍 Pencarian lokasi dengan Nominatim API
- 📍 Click-to-select koordinat
- 🏠 Reverse geocoding untuk mendapatkan alamat otomatis
- 📱 Responsive design
- ⚡ Mudah dikonfigurasi dan reusable
Instalasi
1. Include CSS dan JavaScript
Tambahkan di section Styles dan Scripts pada view Anda:
@section Styles {
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<link rel="stylesheet" href="~/css/leaflet-map-picker.css" />
}
@section Scripts {
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="~/js/leaflet-map-picker.js"></script>
}
Penggunaan
Metode 1: Menggunakan Partial View (Recommended)
Langkah 1: Tambahkan Input Fields untuk Latitude dan Longitude
<fieldset class="fieldset">
<legend class="fieldset-legend">Latitude</legend>
<input type="number" step="any" class="input" id="latitude-input" name="latitude" placeholder="Latitude" />
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Longitude</legend>
<input type="number" step="any" class="input" id="longitude-input" name="longitude" placeholder="Longitude" />
</fieldset>
Langkah 2: Include Partial View
<div class="mt-6">
@{
ViewData["MapId"] = "map-picker";
ViewData["LatInputId"] = "latitude-input";
ViewData["LngInputId"] = "longitude-input";
ViewData["SearchInputId"] = "search-location";
ViewData["SearchResultsId"] = "search-results";
ViewData["ClearSearchBtnId"] = "clear-search";
ViewData["Label"] = "Pilih Lokasi di Peta";
}
@await Html.PartialAsync("_LeafletMapPicker")
</div>
Langkah 3: Initialize JavaScript Component
@section Scripts {
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="~/js/leaflet-map-picker.js"></script>
<script>
window.leafletMapPickerInstance = new LeafletMapPicker({
mapElementId: 'map-picker',
latInputId: 'latitude-input',
lngInputId: 'longitude-input',
searchInputId: 'search-location',
searchResultsId: 'search-results',
clearSearchBtnId: 'clear-search',
alamatInputSelector: 'textarea[name="alamat_lengkap"]', // Optional
initialLat: -6.2088,
initialLng: 106.8456,
initialZoom: 12
});
</script>
}
Metode 2: HTML Manual
<div class="leaflet-map-picker-container">
<label class="text-sm font-semibold text-gray-700 mb-2 block">
<i class="ph ph-map-pin me-2"></i>
Pilih Lokasi di Peta
</label>
<!-- Search Box -->
<div class="leaflet-map-picker-search">
<div class="relative">
<input
type="text"
id="search-location"
class="input leaflet-map-picker-search-input"
placeholder="Cari lokasi (nama tempat, alamat, kota)..."
autocomplete="off"
/>
<i class="ph ph-magnifying-glass leaflet-map-picker-search-icon"></i>
<button
type="button"
id="clear-search"
class="leaflet-map-picker-clear-btn hidden"
>
<i class="ph ph-x"></i>
</button>
</div>
<div id="search-results" class="leaflet-map-picker-results hidden"></div>
</div>
<div id="map-picker" class="leaflet-map-picker"></div>
<p class="leaflet-map-picker-help-text">
<i class="ph ph-info me-1"></i>
Cari lokasi menggunakan search box di atas, atau klik pada peta untuk menentukan lokasi secara manual
</p>
</div>
Konfigurasi Options
| Option | Type | Default | Deskripsi |
|---|---|---|---|
mapElementId |
string | 'map-picker' |
ID elemen untuk map container |
latInputId |
string | 'latitude-input' |
ID input field untuk latitude |
lngInputId |
string | 'longitude-input' |
ID input field untuk longitude |
searchInputId |
string | 'search-location' |
ID input field untuk search box |
searchResultsId |
string | 'search-results' |
ID elemen untuk search results dropdown |
clearSearchBtnId |
string | 'clear-search' |
ID button untuk clear search |
alamatInputSelector |
string | null |
CSS selector untuk input alamat (optional) |
initialLat |
number | -6.2088 |
Latitude awal map (Jakarta) |
initialLng |
number | 106.8456 |
Longitude awal map (Jakarta) |
initialZoom |
number | 12 |
Zoom level awal |
maxZoom |
number | 18 |
Maximum zoom level |
minZoom |
number | 4 |
Minimum zoom level |
searchDebounceMs |
number | 500 |
Debounce delay untuk search (ms) |
countryCode |
string | 'id' |
Country code untuk filter pencarian |
language |
string | 'id' |
Language untuk API results |
ViewData Options untuk Partial View
| Key | Type | Default | Deskripsi |
|---|---|---|---|
MapId |
string | 'map-picker' |
ID untuk map element |
LatInputId |
string | 'latitude-input' |
ID untuk latitude input |
LngInputId |
string | 'longitude-input' |
ID untuk longitude input |
SearchInputId |
string | 'search-location' |
ID untuk search input |
SearchResultsId |
string | 'search-results' |
ID untuk search results |
ClearSearchBtnId |
string | 'clear-search' |
ID untuk clear button |
Label |
string | 'Pilih Lokasi di Peta' |
Label text |
HelpText |
string | Default help text | Help text di bawah map |
ShowLabel |
bool | true |
Tampilkan label |
ShowSearch |
bool | true |
Tampilkan search box |
ShowHelpText |
bool | true |
Tampilkan help text |
Public API Methods
getCoordinates()
Mendapatkan koordinat saat ini.
const coords = leafletMapPickerInstance.getCoordinates();
console.log(coords); // { lat: -6.2088, lng: 106.8456 }
setCoordinates(lat, lng, updateMarker = true)
Set koordinat secara programmatic.
leafletMapPickerInstance.setCoordinates(-6.2088, 106.8456, true);
destroy()
Clean up instance dan event listeners.
leafletMapPickerInstance.destroy();
Contoh Lengkap
@{
ViewData["Title"] = "Edit Lokasi";
}
@section Styles {
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<link rel="stylesheet" href="~/css/leaflet-map-picker.css" />
}
<form method="post">
<div class="grid grid-cols-2 gap-4">
<fieldset class="fieldset">
<legend class="fieldset-legend">Latitude</legend>
<input type="number" step="any" class="input" id="latitude-input" name="latitude" value="-6.2088" />
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Longitude</legend>
<input type="number" step="any" class="input" id="longitude-input" name="longitude" value="106.8456" />
</fieldset>
</div>
<fieldset class="fieldset">
<legend class="fieldset-legend">Alamat</legend>
<textarea class="textarea" name="alamat_lengkap" placeholder="Alamat lengkap"></textarea>
</fieldset>
@{
ViewData["MapId"] = "map-picker";
ViewData["LatInputId"] = "latitude-input";
ViewData["LngInputId"] = "longitude-input";
ViewData["SearchInputId"] = "search-location";
ViewData["SearchResultsId"] = "search-results";
ViewData["ClearSearchBtnId"] = "clear-search";
ViewData["Label"] = "Pilih Lokasi di Peta";
}
@await Html.PartialAsync("_LeafletMapPicker")
<button type="submit" class="btn btn-primary">Simpan</button>
</form>
@section Scripts {
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="~/js/leaflet-map-picker.js"></script>
<script>
window.leafletMapPickerInstance = new LeafletMapPicker({
mapElementId: 'map-picker',
latInputId: 'latitude-input',
lngInputId: 'longitude-input',
searchInputId: 'search-location',
searchResultsId: 'search-results',
clearSearchBtnId: 'clear-search',
alamatInputSelector: 'textarea[name="alamat_lengkap"]',
initialLat: -6.2088,
initialLng: 106.8456,
initialZoom: 12
});
</script>
}
Custom Styling
Anda bisa override CSS classes untuk custom styling:
/* Custom map height */
.leaflet-map-picker {
height: 500px;
}
/* Custom search box styling */
.leaflet-map-picker-search-input {
border-color: #your-color;
}
/* Custom search results */
.leaflet-map-picker-result-item:hover {
background-color: #your-color;
}
Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
Dependencies
- Leaflet 1.9.4+
- OpenStreetMap (Tile Layer)
- Nominatim API (Geocoding)
Troubleshooting
Map tidak muncul
- Pastikan Leaflet CSS dan JS sudah ter-load
- Periksa console untuk error
- Pastikan element ID sudah benar
Search tidak bekerja
- Pastikan ada koneksi internet
- Nominatim API memiliki rate limit
- Periksa browser console untuk error
Koordinat tidak update
- Pastikan input ID sudah benar
- Periksa attribute
step="any"pada input number
License
MIT License
Author
Bank Sampah Development Team