Weave Code
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

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require dotswan/filament-map-picker
    

    For Filament v3:

    composer require dotswan/filament-map-picker:"^1.8"
    
  2. 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)
    
  3. Where to Look First:


Implementation Patterns

Basic Workflow

  1. 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),
        ]);
    }
    
  2. 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,
            ]);
        });
    
  3. 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
        );
    

Advanced Patterns

  1. 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');
    
  2. 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
    
  3. Live Location Updates: Track user location in real-time:

    Map::make('live_location')
        ->liveLocation(true, true, 5000) // Update every 5 seconds
        ->showMyLocationButton(true);
    
  4. Boundary Constraints: Restrict map interactions to a specific region:

    Map::make('location')
        ->boundaries(true, 49.5, -11, 61, 2) // British Isles
        ->minZoom(8);
    
  5. 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);
    
  6. 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');
            }),
    ]);
    

Integration Tips

  • 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');
    

Gotchas and Tips

Common Pitfalls

  1. State Path Conflicts:

    • If you don’t specify a statePath, the field defaults to an empty string, which can cause issues with nested forms or complex state management.
    • Fix: Explicitly set statePath for nested fields:
      Map::make('location')
          ->statePath('address.location')
      
  2. GeoMan Performance:

    • Drawing complex geometries (e.g., large polygons) can lag or freeze the map.
    • Fix: Limit the number of editable layers or disable geoManEditable for read-only displays.
  3. Live Location Permissions:

    • Browsers block live location updates unless explicitly allowed by the user.
    • Fix: Inform users with a tooltip or modal:
      Map::make('location')
          ->liveLocation(true, true, 5000)
          ->extraControl(['showPermissionPrompt' => true]);
      
  4. Boundary Zoom Issues:

    • Setting boundaries without adjusting minZoom may cause the map to appear blank or unzoomable.
    • Fix: Calculate minZoom based on your boundary size (e.g., minZoom(8) for continental boundaries).
  5. GeoJSON Serialization:

    • Ensure 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);
      }
      
  6. Marker Visibility:

    • If showMarker(false) is set, the map will still track coordinates but won’t display a visual marker.
    • Fix: Verify showMarker(true) is set if you need visual feedback.
  7. Retina Detection Conflicts:

    • Some themes or CSS may interfere with retina tile detection.
    • Fix: Disable retina detection if issues arise:
      Map::make('location')
          ->detectRetina(false);
      

Debugging Tips

  1. Console Logs:

    • Use browser dev tools to inspect map events (e.g., marker-moved, location-updated).
    • Add temporary dd() or Log::debug() calls in afterStateUpdated to verify data flow.
  2. Map Initialization:

    • If the map fails to load, check:
      • Tile URLs: Ensure tilesUrl is accessible (e.g., test https://tile.openstreetmap.org/{z}/{x}/{y}.png in your browser).
      • CORS: Custom tile providers may require CORS headers.
      • Dependencies: Verify Leaflet.js and GeoMan assets are loaded (check resources/views/vendor/filament-map-picker/).
  3. GeoMan Issues:

    • Clear browser cache if GeoMan tools appear broken after updates.
    • Disable individual GeoMan features (e.g., drawPolygon(false)) to isolate problems.
  4. State Hydration:

    • If coordinates aren’t loading from the database, verify:
      • Your model’s latitude/longitude fields are populated.
      • The afterStateHydrated closure is correctly mapping record data to the field’s state.

Extension Points

  1. Custom Controls: Extend the map with additional controls using extraControl:
    Map::make('location')
    
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle