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

Searchable Select Laravel Package

sloveniangooner/searchable-select

A Blade-ready Laravel package that adds a fast, searchable select dropdown to forms. It supports filtering large option lists, AJAX/server-side search, and a clean, customizable UI for quicker, more accurate single-value selection.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Confirm compatibility before anything else. This is a single-maintainer Nova field with no dependents, so the first step is reading composer.json in the repo for the laravel/nova constraint. Nova 4+ moved to Vue 3 and the laravel-nova mixin/FormField contract changed; a field built for Nova 3 will install fine and then render as a blank row with no error in the UI.

composer require sloveniangooner/searchable-select
php artisan nova:publish   # only if the package registers assets via a service provider

Where to look first, in this order:

Path Why
composer.json Nova version constraint + whether dist/ is committed
src/*.php The field class — the real public API (method names vary wildly between these small packages)
src/*ServiceProvider.php Nova::script() call and the path it points at
resources/js/field.js / dist/js/field.js Which upstream component it wraps (vue-multiselect, v-select, custom)
README.md Usage snippet — take it as a starting point, verify against src/

First use case — the one this package actually earns its keep on: a plain Select field backed by a non-relationship options list large enough (say 300+ rows) that Nova's native <select> becomes unusable to scroll. If you're selecting a related model, stop here and use Nova's built-in BelongsTo::make('Category')->searchable() instead — it already does server-side search and won't rot.

use SlovenianGooner\SearchableSelect\SearchableSelect;

public function fields(NovaRequest $request)
{
    return [
        SearchableSelect::make('Category', 'category_id')
            ->options(Category::orderBy('name')->pluck('name', 'id')->all())
            ->rules('required', 'exists:categories,id'),
    ];
}

Verify the method names (options, searchable, placeholder) against src/ before committing — treat the snippet above as a sketch, not documentation.

Implementation Patterns

Static vs. dynamic options. Options are serialized into the field's JSON payload at resource-fetch time, so any pluck() inside fields() runs on every index, detail, and form request for that resource. Keep the list small or wrap it:

->options(Cache::rememberForever('category-options', fn () =>
    Category::orderBy('name')->pluck('name', 'id')->all()
))

If the option set is genuinely large, ->onlyOnForms() so it never touches the index query.

Storing IDs, displaying labels. Two patterns, pick one and be consistent:

// A: keyed array — the key is stored, the value is displayed
SearchableSelect::make('Category', 'category_id')
    ->options(Category::pluck('name', 'id')->all())

// B: resolve/display hooks when the option source isn't a plain map
SearchableSelect::make('Category', 'category_id')
    ->options($this->categoryOptions())
    ->resolveUsing(fn ($value) => $value)
    ->displayUsing(fn ($value) => Category::find($value)?->name)

Pattern A is the one these fields are usually designed around and the one least likely to surprise you.

Dependent selects. Nova's dependsOn re-runs the resource's fields() callback via a /nova-api/.../creation-fields or .../update-fields round trip, so a closure over $request works:

SearchableSelect::make('City', 'city_id')
    ->options(fn () => City::where('country_id', $request->country_id)
        ->pluck('name', 'id')->all()),

This costs a request per change — acceptable for a form, painful if you chain three.

Validation is on you. Unlike BelongsTo, a searchable select has no opinion about the underlying table. Always add ->rules('required', 'exists:categories,id') or you'll get a clean-looking dropdown that happily persists garbage via a crafted request.

Index column formatting. These fields often render raw IDs on the index. Add ->displayUsing(...) or ->hideFromIndex() explicitly rather than assuming.

Gotchas and Tips

  • Blank field = asset problem, not PHP problem. Open DevTools, look for Unknown custom element <searchable-select> or a 404 on /nova-api/.... Fixes: check dist/js/field.js exists in vendor/sloveniangooner/searchable-select/; if not, cd into the vendor dir and npm install && npm run prod. Clear storage/framework/cache and re-run php artisan nova:publish.
  • Vue 3 breakage is silent. A Nova 3 field on Nova 4 mounts nothing, logs a Vue warning, and shows an empty row. Test on one form before rolling it out.
  • 0 vs "0". PHP array keys become JS object keys become strings. If any option ID is 0 or the value is null, loose comparison in the wrapped component can leave the field looking empty while the DB has a value. Use non-zero integer keys.
  • Empty string vs. null. Clearing the field commonly persists '', which blows up a nullable integer column (or FK constraint). Add ->nullable() and confirm what the component emits by inspecting the PUT payload.
  • Search scope. Most of these fields search client-side over the already-loaded array. That's fine for a few hundred options and a bad idea at 20k — the payload ships on every form load. There's usually no remote-search hook; if you need one, use BelongsTo::searchable() or a custom field.
  • Server-side option resolution caching. If you cache options, remember to bust the cache when a category is created. A saved model observer is the cheap fix.
  • Extension points are thin. Expect a single field class with no events or slots. Forking into nova-components/ and swapping the Vue component is usually faster than fighting the package.
  • Maintenance risk is the headline. Zero stars, zero dependents, one maintainer. Before you build anything on it, check the last commit date. If it's stale, budget a half-day to vendor/fork it — and prefer Nova's built-ins (Select::make()->options()->searchable() in Nova 4+) as the exit ramp.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console