Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Map Picker Laravel Package

eg-mohamed/filament-map-picker

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and publish assets.

    composer require eg-mohamed/filament-map-picker
    php artisan vendor:publish --tag="filament-map-picker-config"   # optional
    php artisan filament:assets                                     # required — the map JS/CSS ships as a Filament asset
    

    If your panel registers plugins explicitly, add the package plugin to the panel provider; otherwise the form component can be used directly.

  2. Where to look first.

    • The README for the exact component namespace and fluent API for your installed version — these map-picker packages are frequently forked and method names drift (setCenterLocation, showMarker, draggable, tilesUrl).
    • config/filament-map-picker.php after publishing: default centre coordinates, zoom range, tile URL/attribution, and any API key slot.
    • The published Blade view (if the package exposes one) — this is where the Leaflet/Alpine init lives, and it is the first place to look when the map renders blank or half-sized.
  3. First use case. An address/location picker on a Resource form. Add two decimal columns (latitude, longitude, precision 10,7 / 10,7) via migration, then drop the field into the form schema. The component's state is typically an array of lat/lng keys, so hydrate it in mutateFormDataBeforeFill() / mutateFormDataBeforeCreate() rather than trying to bind it straight to a column.

  4. 1.0.1 release: patch bump with an empty changelog (compare link only). No documented features, deprecations, or BC breaks — a low-risk upgrade from 1.0.0. Skim the GitHub compare diff before bumping in production, since silent patches to JS init code are exactly the kind of change that breaks map rendering without a version-visible reason.

Implementation Patterns

Form + persistence. Keep the map field dehydrated into a virtual state and split it into real columns:

MapPicker::make('location')
    ->label('Pick a location')
    ->showMarker()
    ->draggable()
    ->clickable()
    ->live()
    ->afterStateUpdated(function ($state, Set $set) {
        $set('latitude', $state['lat'] ?? null);
        $set('longitude', $state['lng'] ?? null);
    })
    ->dehydrated(false),

Hidden::make('latitude'),
Hidden::make('longitude'),

Hydrate location from the model in mutateFormDataBeforeFill() with ['lat' => $record->latitude, 'lng' => $record->longitude]. Hidden inputs must be present in the schema — Filament only saves fields it knows about.

Reactive two-way binding. Use ->live() on the map and on plain TextInputs for lat/lng if you want users to be able to type coordinates and move the marker. Guard against loops by only $set()-ing when the value actually changed.

Validation. Validate in rules() on the hidden fields, not the map field: ['required', 'numeric', 'between:-90,90'] and ['required', 'numeric', 'between:-180,180']. Add a Rule::requiredIf on the map state if the location is mandatory, otherwise a submitted form with an untouched map quietly persists null.

Table + infolist display. A TextColumn rendering lat/lng as a Google Maps / OpenStreetMap deep link is cheaper than embedding a map in a table row:

TextColumn::make('latitude')
    ->formatStateUsing(fn ($state, $record) => "{$record->latitude}, {$record->longitude}")
    ->url(fn ($record) => "https://www.google.com/maps?q={$record->latitude},{$record->longitude}", true)
    ->openUrlInNewTab(),

Multiple maps on one page. Give each instance a unique statePath/key; duplicate container IDs are a common source of "second map is dead" bugs.

Testing. Drive it through fillForm(['latitude' => ..., 'longitude' => ...]) and assert the DB columns, rather than trying to simulate marker drags in a browser. Keep a small Dusk/browser test for the map-render path only.

Gotchas and Tips

  • Blank or grey map. Nine times out of ten it's unpublished assets (php artisan filament:assets after every upgrade) or a blocked tile server. Check the browser network tab for 404s on the package JS before touching config.
  • Zero-height container. The map sits in a Hidden tab, a wizard step, or a collapsed section and Leaflet initialises at 0px. Fix with an explicit ->height(...)/CSS min-height, or call map.invalidateSize() on the tab/wizard change event.
  • Livewire navigation. SPA-style navigation can leave an orphaned Leaflet instance and a duplicated map. Ensure the Alpine component destroys the map on @destroy, and version-pin the package if you see regressions — this is the area 1.0.1 most plausibly touches given the empty changelog.
  • Precision loss. float columns plus JS number round-tripping will drift coordinates. Use decimal(10,7) and cast to string or decimal:7 in the model.
  • Tile providers. Default OSM tiles are fine for dev and low traffic but have usage policies; for production point tilesUrl at a paid/commercial provider or self-hosted tiles, and keep the attribution string intact. Air-gapped deployments need a self-hosted tile source or this component is unusable.
  • API keys. If you switch to a Google Maps-backed tile layer, keep the key in config/services.php/.env, never in the panel provider, and restrict it by HTTP referrer.
  • CSP. A strict Content-Security-Policy silently breaks tiles and marker icons. Whitelist the tile domain under img-src and connect-src.
  • Extension points. Override the component view via ->view('vendor/filament-map-picker/...') after publishing views; that's the supported escape hatch for custom marker icons, autocomplete search boxes, or geocoding on click (call your geocoder in afterStateUpdated and $set() the address fields).
  • Upgrade hygiene. These plugins move fast and patch releases carry no changelog. Pin an exact version in composer.json ("1.0.1"), read the compare diff on each bump, and keep a smoke test that asserts the form renders and the component class resolves.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support