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 Maps Laravel Package

webbingbrasil/filament-maps

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require webbingbrasil/filament-maps
    

    Publish assets (if needed):

    php artisan vendor:publish --provider="Webbingbrasil\FilamentMaps\FilamentMapsServiceProvider"
    
  2. First Widget: Create a widget extending MapWidget in app/Filament/Widgets/Map.php:

    use Webbingbrasil\FilamentMaps\Widgets\MapWidget;
    
    class Map extends MapWidget {
        protected int $columnSpan = 'full';
        public function getMarkers(): array { return []; }
    }
    

    Register it in app/Providers/Filament/AdminPanelProvider.php:

    public static function panel(Panel $panel): Panel {
        return $panel->widgets([
            \App\Filament\Widgets\Map::class,
        ]);
    }
    
  3. First Use Case: Display a map with a single marker:

    public function getMarkers(): array {
        return [
            Marker::make('Office')->lat(40.7128)->lng(-74.0060)->popup('New York HQ'),
        ];
    }
    

Implementation Patterns

Core Workflows

  1. Marker Management:

    • Dynamic Markers: Fetch from a model (e.g., User::all()) and map to Marker objects:
      public function getMarkers(): array {
          return User::query()
              ->get()
              ->map(fn ($user) => Marker::make($user->name)
                  ->lat($user->latitude)
                  ->lng($user->longitude)
                  ->popup("User: {$user->email}")
              );
      }
      
    • Clustered Markers: Enable clustering via MarkerClusterGroup:
      use Webbingbrasil\FilamentMaps\MarkerClusterGroup;
      
      public function getMarkers(): array {
          return [
              MarkerClusterGroup::make()->markers([
                  Marker::make('A')->lat(1)->lng(1),
                  Marker::make('B')->lat(2)->lng(2),
              ]),
          ];
      }
      
  2. Layer Integration:

    • Add custom tile layers (e.g., OpenStreetMap, custom WMS):
      public function getLayers(): array {
          return [
              \Webbingbrasil\FilamentMaps\Layers\OpenStreetMap::make(),
              \Webbingbrasil\FilamentMaps\Layers\DarkModeTile::make(),
          ];
      }
      
  3. Action Integration:

    • Attach Filament actions to map controls:
      public function getActions(): array {
          return [
              Actions\ZoomAction::make()->label('Zoom In'),
              Actions\CenterMapAction::make()->label('Center Here'),
              \Filament\Actions\Action::make('Refresh')
                  ->action(fn () => $this->refreshMarkers())
                  ->icon('heroicon-o-arrow-path'),
          ];
      }
      
  4. Event Handling:

    • Listen to map events (e.g., moveend) via JavaScript:
      protected string $extraJs = '
          map.on("moveend", function() {
              console.log("Map moved to:", map.getCenter());
          });
      ';
      

Advanced Patterns

  • Geocoding: Use the Geocoder helper to convert addresses to coordinates:

    use Webbingbrasil\FilamentMaps\Support\Geocoder;
    
    $coordinates = Geocoder::geocode('1600 Amphitheatre Parkway, Mountain View');
    Marker::make('Google HQ')->lat($coordinates['lat'])->lng($coordinates['lng']);
    
  • Custom Controls: Extend MapWidget to add custom Leaflet controls:

    class CustomMap extends MapWidget {
        protected string $extraJs = '
            L.control.scale().addTo(map);
        ';
    }
    
  • Performance: For large datasets, implement lazy-loading:

    public function getMarkers(): array {
        return Marker::make('Cluster')->lat(0)->lng(0)
            ->clusterOptions(['spiderfyOnMaxZoom': true])
            ->popup('Click to load details');
    }
    

Gotchas and Tips

Common Pitfalls

  1. Leaflet Version Conflicts:

    • Ensure no other package includes Leaflet (e.g., spatie/laravel-geocoder). Use npm for custom builds if needed.
    • Fix: Check resources/js/app.js for duplicate Leaflet includes.
  2. Marker Overlapping:

    • Default clustering may not work for >100 markers. Use MarkerClusterGroup with custom options:
      MarkerClusterGroup::make()->options([
          'spiderfyOnMaxZoom': true,
          'maxClusterRadius': 80,
      ]);
      
  3. Dark Mode Issues:

    • DarkModeTile layer may not adapt to Filament’s dark mode. Override with CSS:
      protected string $extraCss = '
          .leaflet-dark-mode .leaflet-tile {
              filter: brightness(0.8) !important;
          }
      ';
      
  4. Action Button Styling:

    • Filament actions in map controls may inherit incorrect styling. Force classes:
      Actions\CenterMapAction::make()->icon('heroicon-o-map-pin')->extraClasses('text-blue-500');
      
  5. Geolocation Errors:

    • Browser geolocation prompts may block silently. Handle errors in extraJs:
      protected string $extraJs = '
          map.locate({ setView: true, maxZoom: 16 });
          map.on("locationerror", function(e) {
              alert(e.message);
          });
      ';
      

Debugging Tips

  • Console Logs: Add debug logs via extraJs:

    protected string $extraJs = '
        map.on("click", function(e) {
            console.log("Clicked at:", e.latlng);
        });
    ';
    
  • Inspect Elements: Use browser dev tools to inspect Leaflet containers (e.g., .leaflet-container). Common issues:

    • Missing position: relative on parent containers.
    • Z-index conflicts with Filament modals.
  • Clear Cache: After updates, run:

    php artisan filament:cache-reset
    npm run dev
    

Extension Points

  1. Custom Layers: Extend Webbingbrasil\FilamentMaps\Layers\Layer to create reusable layers:

    class CustomLayer extends Layer {
        public function getUrl(): string {
            return 'https://custom-tile-server/{z}/{x}/{y}.png';
        }
        public function getOptions(): array {
            return ['attribution': 'Custom'];
        }
    }
    
  2. Marker Icons: Replace default icons with custom SVG/URLs:

    Marker::make('Custom')->icon('https://example.com/custom-icon.png');
    
  3. Polygons/Circles: Use Leaflet’s L.polygon/L.circle via extraJs:

    protected string $extraJs = '
        L.circle([51.505, -0.09], 500, { color: "red" }).addTo(map);
    ';
    
  4. Server-Side Rendering: For SSR compatibility, disable Leaflet’s interactive: true in extraJs:

    protected string $extraJs = '
        map.options.interactive = false;
    ';
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui