yemenpoint/filament-google-map-location-picker
A Filament form field for picking locations on Google Maps. Search or drag a marker to capture latitude and longitude, with optional address details saved to your model. Quick setup for Laravel Filament apps and location-based forms.
This is a small, single-purpose Filament form component: it drops a Google Map into a form, lets the user click/drag a marker, and writes the chosen coordinates back to your model. Treat it as a coordinate picker, not a full mapping suite (no polygons, no multi-marker, no clustering).
Minimal steps:
composer require yemenpoint/filament-google-map-location-picker
php artisan vendor:publish --tag="filament-google-map-location-picker-config" # if the tag exists
.env:
GOOGLE_MAPS_API_KEY=AIza...
and clear the config cache (php artisan config:clear) — the key is read server-side and handed to the Livewire/Alpine component.src/Forms/Components/ in the repo, but the shape is:
use Yemenpoint\FilamentGoogleMapLocationPicker\Forms\Components\GoogleMapLocationPicker;
GoogleMapLocationPicker::make('location')
->label('Store location');
Where to look first: the README for the exact class name and setter methods (the package predates Filament v3 conventions and the docs are thin), then src/ for the Alpine view and config file. The config file is where the API key and default map center/zoom live.
First use case: a StoreResource create/edit form where an admin pins the shop on a map. Store the result in latitude / longitude decimal columns, and render a read-only "View on map" link in the table.
Two-column storage (most common). Keep latitude and longitude as separate decimal(10,7) columns. Cast them in the model and let the field populate both:
// migration
$table->decimal('latitude', 10, 7)->nullable();
$table->decimal('longitude', 10, 7)->nullable();
If the component writes to a single JSON column, hydrate/dehydrate manually in the form — check the source before committing to a schema.
Edit hydration. The biggest day-to-day friction is re-opening an edit form and finding the map centered on the default city instead of the saved pin. Pass the existing values explicitly:
GoogleMapLocationPicker::make('location')
->default(fn ($record) => $record
? ['lat' => $record->latitude, 'lng' => $record->longitude]
: null)
If the package supports it, prefer the native defaultLocation() / defaultZoom() setters over ->default(), since the field's internal state shape is package-specific.
Reverse geocoding into an address field. Pair the picker with a text input and resolve the address on save (or on change via ->live() + afterStateUpdated). Doing it server-side in the resource's mutateFormDataBeforeSave() keeps the API key's server-side geocoding calls separate from the browser key:
protected function mutateFormDataBeforeSave(array $data): array
{
$data['address'] ??= app(Geocoder::class)
->reverse($data['latitude'], $data['longitude']);
return $data;
}
Reusable schema. Wrap the field in a LocationPickerSchema::make() static method or a HasLocation trait so every resource that needs a pin gets identical config (zoom, restrictions, required validation).
Validation. The picker gives you coordinates, not correctness. Add bounds validation:
->rules(['required', 'numeric', 'between:-90,90']) // per field if split
Table display. Don't embed a map per row — it's slow and burns API quota. Render a link instead:
Tables\Columns\TextColumn::make('latitude')
->formatStateUsing(fn ($record) => $record->latitude
? "{$record->latitude}, {$record->longitude}"
: '—')
->url(fn ($record) => $record->latitude
? "https://maps.google.com/?q={$record->latitude},{$record->longitude}"
: null, true);
Forms\Components API mismatches. Pin the version, test in a branch, and budget time to fork. With 0 dependents and 29 stars, upstream fixes are unlikely.GOOGLE_MAPS_API_KEY in .env, run php artisan config:clear (or optimize:clear). A stale cached config silently renders a blank/grey map.Livewire.hook('message.processed') re-init, the map shows grey until you resize the window. Fix by ensuring a fixed height on the container via the field's ->extraAttributes() or a small CSS override.ApiNotActivatedMapError / RefererNotAllowedMapError, (2) API key present in the rendered HTML, (3) Maps JS API enabled + billing on, (4) container height, (5) config cache.required_with rule or a saving observer that nulls both if either is missing.->draggable(true) only if the underlying Google Maps config supports it, and consider a "use my location" button backed by the browser Geolocation API as a fallback.cheesegrits/filament-google-maps is the actively maintained, feature-rich alternative (multi-marker, clustering, geocoding, draw tools). This package is worth it only for a tiny single-pin admin form where you're already pinned to its Filament version.How can I help you explore Laravel packages today?