bank-sampah/wwwroot/js/leaflet-map-picker.README.md

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

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