310 lines
9.5 KiB
Markdown
310 lines
9.5 KiB
Markdown
# 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:
|
|
|
|
```cshtml
|
|
@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
|
|
|
|
```cshtml
|
|
<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
|
|
|
|
```cshtml
|
|
<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
|
|
|
|
```cshtml
|
|
@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
|
|
|
|
```html
|
|
<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.
|
|
|
|
```javascript
|
|
const coords = leafletMapPickerInstance.getCoordinates();
|
|
console.log(coords); // { lat: -6.2088, lng: 106.8456 }
|
|
```
|
|
|
|
### `setCoordinates(lat, lng, updateMarker = true)`
|
|
Set koordinat secara programmatic.
|
|
|
|
```javascript
|
|
leafletMapPickerInstance.setCoordinates(-6.2088, 106.8456, true);
|
|
```
|
|
|
|
### `destroy()`
|
|
Clean up instance dan event listeners.
|
|
|
|
```javascript
|
|
leafletMapPickerInstance.destroy();
|
|
```
|
|
|
|
## Contoh Lengkap
|
|
|
|
```cshtml
|
|
@{
|
|
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:
|
|
|
|
```css
|
|
/* 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
|