dotswan/filament-map-picker
Filament v3 map picker field with OpenStreetMap integration. Let users select a location and get real-time coordinates when the marker moves. Customize controls and marker styling, with optional GeoMan tools for drawing and editing shapes.
Installation:
composer require dotswan/filament-map-picker
For Filament v3:
composer require dotswan/filament-map-picker:"^1.8"
First Use Case:
Add the Map field to a Filament resource form:
use Dotswan\MapPicker\Fields\Map;
Map::make('location')
->label('Location')
->columnSpanFull()
->defaultLocation(latitude: 40.4168, longitude: -3.7038)
Where to Look First:
Form Integration:
Use the Map field in Filament forms to capture geographic coordinates.
public static function form(Form $form): Form
{
return $form->schema([
Map::make('coordinates')
->label('Select Location')
->defaultLocation(latitude: 51.5074, longitude: -0.1278) // Default to London
->zoom(12),
]);
}
State Management: Handle state updates and hydration to sync with your database model:
Map::make('location')
->afterStateUpdated(function (Set $set, ?array $state): void {
$set('latitude', $state['lat']);
$set('longitude', $state['lng']);
})
->afterStateHydrated(function ($state, $record, Set $set): void {
$set('location', [
'lat' => $record->latitude,
'lng' => $record->longitude,
]);
});
Dynamic Defaults: Use closures to dynamically set default locations based on records:
Map::make('location')
->defaultLocation(
latitude: fn ($record) => $record?->latitude ?? 51.5074,
longitude: fn ($record) => $record?->longitude ?? -0.1278
);
GeoMan Integration: Enable advanced map editing features like drawing polygons, polylines, and circles:
Map::make('area')
->geoMan(true)
->drawPolygon(true)
->drawPolyline(true)
->drawCircle(true)
->setColor('#3388ff')
->setFilledColor('#cad9ec');
Range Selection: Link the map to a range field (e.g., distance) to visualize areas dynamically:
Map::make('location')
->rangeSelectField('distance')
->defaultLocation(latitude: 40.7128, longitude: -74.0060); // Default to NYC
Live Location Updates: Track user location in real-time:
Map::make('live_location')
->liveLocation(true, true, 5000) // Update every 5 seconds
->showMyLocationButton(true);
Boundary Constraints: Restrict map interactions to a specific region:
Map::make('location')
->boundaries(true, 49.5, -11, 61, 2) // British Isles
->minZoom(8);
Infolist Display:
Use MapEntry to display maps in Filament infolists:
use Dotswan\MapPicker\Infolists\MapEntry;
MapEntry::make('location')
->defaultLocation(
latitude: fn ($record) => $record?->latitude ?? 0,
longitude: fn ($record) => $record?->longitude ?? 0
)
->draggable(false);
Custom Actions: Trigger map updates via Filament actions:
Actions::make([
Action::make('Reset Location')
->action(function (Set $set, $livewire) {
$set('location', ['lat' => 40.7128, 'lng' => -74.0060]);
$livewire->dispatch('refreshMap');
}),
]);
Database Sync:
Ensure your model has fields to store latitude, longitude, and optionally geojson for GeoMan data.
$table->decimal('latitude', 10, 8)->nullable();
$table->decimal('longitude', 11, 8)->nullable();
$table->json('geojson')->nullable();
Custom Styling:
Use extraStyles to override default map container styles:
Map::make('location')
->extraStyles([
'min-height: 400px',
'border-radius: 8px',
'border: 1px solid #e2e8f0',
]);
Tile Customization: Replace default OpenStreetMap tiles with custom providers (e.g., Mapbox, Google Maps):
Map::make('location')
->tilesUrl('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={token}')
->attribution('© Mapbox');
State Path Conflicts:
statePath, the field defaults to an empty string, which can cause issues with nested forms or complex state management.statePath for nested fields:
Map::make('location')
->statePath('address.location')
GeoMan Performance:
geoManEditable for read-only displays.Live Location Permissions:
Map::make('location')
->liveLocation(true, true, 5000)
->extraControl(['showPermissionPrompt' => true]);
Boundary Zoom Issues:
boundaries without adjusting minZoom may cause the map to appear blank or unzoomable.minZoom based on your boundary size (e.g., minZoom(8) for continental boundaries).GeoJSON Serialization:
geojson data is properly serialized/deserialized in your model:
// In your model's accessors/mutators:
public function getGeoJsonAttribute($value)
{
return json_decode($value, true);
}
public function setGeoJsonAttribute($value)
{
$this->attributes['geojson'] = json_encode($value);
}
Marker Visibility:
showMarker(false) is set, the map will still track coordinates but won’t display a visual marker.showMarker(true) is set if you need visual feedback.Retina Detection Conflicts:
Map::make('location')
->detectRetina(false);
Console Logs:
marker-moved, location-updated).dd() or Log::debug() calls in afterStateUpdated to verify data flow.Map Initialization:
tilesUrl is accessible (e.g., test https://tile.openstreetmap.org/{z}/{x}/{y}.png in your browser).resources/views/vendor/filament-map-picker/).GeoMan Issues:
drawPolygon(false)) to isolate problems.State Hydration:
latitude/longitude fields are populated.afterStateHydrated closure is correctly mapping record data to the field’s state.extraControl:
Map::make('location')
How can I help you explore Laravel packages today?