cheesegrits/filament-google-maps

Refresh loadFeaturesCollection on drawingField change

Opened this issue · 1 comments

luttje commented

Hi, thanks for this awesome package! I'm making good use of it in two projects and it's working great.

However what would help me is the following feature when using the Map field: to make loadFeaturesCollection (in js/filament-google-maps.js) get called again when the drawingField state changes.

I would use this to limit the amount of polygons being drawn. But if it worked it would allow a lot of mutations on the PHP-side, to be reflected in the layer drawings.

Here's the code I tried in between START and END:

public static function form(Form $form): Form
{
    return $form
        ->schema([
            //...

            // Validation works fine
            Forms\Components\Hidden::make('geo_fence_json')
                ->rules([
                    function() {
                        return function (string $attribute, $value, Closure $fail) {
                            try {
                                $geoFence = Geometry::fromJson($value);

                                if (!$geoFence instanceof Polygon) {
                                    $fail('The :attribute contains too many polygons.');
                                }
                            } catch (Exception $e) {
                                $fail('The :attribute is invalid.');
                            }
                        };
                    }
                ])
                // START
                // This fails because cheesegrits/filament-google-maps only looks in the drawingField upon first load
                ->afterStateUpdated(function (?string $state, ?string $old, Set $set) {
                    $geoFence = Geometry::fromJson($state);

                    if ($geoFence instanceof MultiPolygon) {
                        $polygon = $geoFence[0];
                        $featureCollection = GeoBuilder::wrapFeatureCollectionJson($polygon);
                        $set('geo_fence_json', $featureCollection);
                    } elseif ($geoFence instanceof Polygon) {
                        //$polygon = $geoFence;
                    } else {
                        throw new Exception('The geo fence is invalid.');
                    }
                })
                // END

                // Initial load also works fine
                ->formatStateUsing(function (?Location $record) {
                    if (!$record) {
                        return '{}';
                    }

                    $geoFenceGeometry = $record->geo_fence->toJson();

                    // cheesegrits/filament-google-maps needs the property id to be a guid, we'll re-use the location id
                    $shapeId = $record->id;

                    return GeoBuilder::wrapFeatureCollectionJson($geoFenceGeometry, $shapeId);
                }),

            Map::make('location')
                ->autocomplete(
                    fieldName: 'address_line_1'
                )
                ->reverseGeocode([
                    'address_line_1' => '%S %n',
                    'city' => '%L',
                    'state' => '%A1',
                    'zip_code' => '%z',
                    'country' => '%c',
                ])
                ->defaultLocation([52.1326, 5.2913])
                ->defaultZoom(18)
                ->mapControls([
                    'mapTypeControl' => true,
                    'scaleControl' => true,
                    'streetViewControl' => false,
                    'rotateControl' => true,
                    'fullscreenControl' => false,
                    'searchBoxControl' => false,
                    'zoomControl' => true,
                ])
                ->draggable()
                ->columnSpanFull()
                ->drawingControl()
                ->drawingModes([
                    'polygon' => true,
                ])
                ->drawingField('geo_fence_json')
        ]);
}

(The Geometry, MultiPolygon and Polygon come from asanikovich/laravel-spatial)

Other than this feature request everything works fine. I can set data on initial load (as seen above) and validate (also seen above). Again: awesome package, really saves me a lot of time!

luttje commented

Actually, as I was typing this I realized a nice workaround:

  1. Generate a polygon on create
  2. Only allow editing the polygon by calling ->drawingModes([])
  3. This perfectly limits to a single polygon

I'll leave this issue open since I think it's still a useful feature, but feel free to close it.