Weave 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

Nova Map Address Laravel Package

josrom/nova-map-address

josrom/nova-map-address is a Laravel Nova field for map-based address input. It adds an interactive map to Nova resource forms, letting users search, select, and manage addresses visually so location data is easier to capture and edit in admin panels.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a Laravel Nova form field that embeds Google Maps to capture an address (and typically latitude/longitude) instead of a plain text input. Docs are thin and the package has ~3 stars / 0 dependents, so treat the source as the source of truth.

Minimal path to first render:

  1. Install into a Nova app (Nova 4+ assumed — verify the nova constraint in composer.json before committing):
    composer require josrom/nova-map-address
    php artisan vendor:publish --provider="Josrom\NovaMapAddress\FieldServiceProvider"
    
  2. Configure the Google API key. Nova packages of this shape read from config/services.php or a package config. Set it in .env and clear config:
    GOOGLE_MAPS_API_KEY=your-key
    
    Your key needs Maps JavaScript API and Places API (plus Geocoding API if the package reverse-geocodes on save) enabled in Google Cloud.
  3. Prepare the model/table. The field expects columns for the address and, usually, latitude / longitude (plus a place ID in some versions). Add them if missing:
    $table->string('address')->nullable();
    $table->decimal('latitude', 10, 7)->nullable();
    $table->decimal('longitude', 10, 7)->nullable();
    
  4. Use it in a Nova Resource:
    use Josrom\NovaMapAddress\NovaMapAddress;
    
    public function fields(Request $request)
    {
        return [
            NovaMapAddress::make('Address'),
        ];
    }
    

Where to look first (in this order):

  • src/ for the Field subclass — the public API (make, withMeta, any ->coordinates() style helpers) is defined there.
  • resources/js/ for the Vue component — this tells you exactly which model attributes are read/written and what Google APIs are called.
  • config/ for the key name and default map options (zoom, center, country restrictions).

First use case: a single-address resource (e.g. a Store or Venue) where an admin drops a pin and the street address, lat, and lng persist together. That's the 20% case this package exists for.

Implementation Patterns

Pair it with read-only coordinate fields. The map writes lat/lng as a side effect; expose them for trust/debugging but don't let users hand-edit them into an inconsistent state:

NovaMapAddress::make('Address')
    ->rules('required', 'string', 'max:255'),

Number::make('Latitude')->readonly()->hideFromIndex(),
Number::make('Longitude')->readonly()->hideFromIndex(),

Note the readonly() fields must still be present in the field set for the JS payload to round-trip in some versions — verify in the component before trusting hidden-only.

Normalize on save with a model observer. Google returns formatted addresses that vary run to run; store a canonical form and geocode defensively:

// app/Observers/StoreObserver.php
public function saving(Store $store): void
{
    if ($store->isDirty('address') && $store->latitude === null) {
        // fallback geocode when the map widget wasn't used (imports, API writes)
    }
}

Use it on one "location" field, not five. A common mistake is dropping the map on every resource. Wrap it once and reuse:

// app/Nova/Fields/AddressField.php
class AddressField extends NovaMapAddress
{
    public function __construct($name, $attribute = null, $resolveCallback = null)
    {
        parent::__construct($name, $attribute ?? 'address', $resolveCallback);
        $this->withMeta(['defaultZoom' => 12, 'country' => 'gb']);
    }
}

Push config via meta() rather than editing the published vendor config. When you need per-field behavior (center point, country bias, zoom), ->withMeta([...]) keeps you upgradable and avoids a config fork the maintainer won't support.

Integration with search/filters. Because the field stores discrete latitude/longitude, don't ship a map widget into Nova's index. Compute distance in a custom filter or lens using a Haversine scope on the model, and keep the map strictly a form concern.

Testing. The Google SDK is browser-side, so PHPUnit won't exercise it. Assert the field resolves correctly and that your observer/geocoding fallback works:

it('persists coordinates from a payload', function () {
    $store = Store::factory()->create([
        'address' => '10 Downing St, London',
        'latitude' => 51.5034,
        'longitude' => -0.1276,
    ]);
    expect($store->fresh()->latitude)->toEqual(51.5034);
});

For feature tests via Nova's Nova::actingAs, send the coordinates explicitly — Dusk/browser tests are the only place the widget itself can be validated, and even then only with a live key.

Gotchas and Tips

  • API key restrictions will bite you first. Restrict the key by HTTP referrer to your Nova host (not IP, not "None"), and enable Maps JavaScript API, Places API, and Geocoding API explicitly. A missing one shows as a silently blank map or an autocomplete that never resolves — check the browser console for Google Maps JavaScript API error: ....
  • Nova assets must be republished after upgrades. If the field renders as an empty box or [Vue warn]: Unknown custom element, run php artisan nova:publish and hard-refresh; stale public/vendor/ assets are the #1 "it's broken" cause.
  • Billing/quota surprise. Places Autocomplete bills per keystroke-session; add a components=country:xx restriction and a session token in the component if you're tuning costs. In CI and local dev, mock or stub the key so test suites don't hammer the API.
  • Attribute mismatch is silent. If the DB column is address_line_1 but the field defaults to address, saves look successful but persist null. Confirm the attribute in src/ before wiring the migration.
  • Nova version drift. With 3 stars and no dependents, assume no CI matrix. Check composer.json for laravel/nova constraints; if it targets Nova 3, expect the Vue 2 component to fail under Nova 4/5's Vue 3 runtime. Forking the JS is a realistic outcome.
  • Decimal precision. Use decimal(10,7) (not float) for lat/lng — MySQL float rounding will make pins drift by meters and break exact-match comparisons in filters.
  • Read the component for the real contract. The Vue file is the actual spec: it defines which attributes are emitted, whether it reverse-geocodes, and what meta keys it honors. When behavior surprises you, grep resources/js before opening an issue.
  • Extension points worth knowing: withMeta() for per-field config, overriding the field class to hard-code defaults, and your model's saving/saved events for geocoding fallbacks (imports, API writes, seeders). There is no event system in the package itself — don't expect hooks.
  • Bus-factor risk. Zero dependents means you're the canary. Pin the version in composer.json, and if it becomes load-bearing, vendor the field into app/Nova/Fields so a future Laravel/Nova bump doesn't strand you.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib