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

famcare/searchable-select

A Laravel package that adds a searchable select input to your forms, letting users filter long option lists with instant AJAX-powered search. Drop it into Blade views, point it at any model or endpoint, and get a lightweight dropdown without extra frontend work.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a community fork of a deleted Nova field package, so treat the repository itself as the primary documentation. Before writing any code, do three things:

  1. Install and pin the version explicitly. With 1 star, no dependents, and a single 2024 release, you do not want a floating constraint pulling in an unexpected change:

    composer require famcare/searchable-select:^1.0
    

    Check the tag that actually exists (composer show famcare/searchable-select --all) and pin to it.

  2. Read the source before the README. Open src/ and look for the field class (typically SearchableSelect.php), its resources/js/ component, and any config/ or service provider. In a fork like this, the README is usually inherited verbatim from the original package and may describe options that no longer exist or have been renamed. The class's public function signatures are the ground truth.

  3. Confirm it registers with Nova. Run php artisan nova:asset (or nova:publish depending on your Nova version) and load a simple resource form to verify the field renders before building on it.

First use case: replacing a BelongsTo or Select field whose option list has outgrown a plain dropdown — think a category tree, a country list, or a User picker over thousands of rows. The minimal form field looks like:

use Famcare\SearchableSelect\SearchableSelect;

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

If that renders and filters as you type, the package is working and everything else is configuration.

Implementation Patterns

Static option lists (small-to-medium cardinality). Pass an associative array or Collection via ->options(). Eager-load or pluck once in the fields() call — do not query inside the search callback. For anything over a few hundred rows, prefer a search endpoint over shipping all options into the page.

Relationship-backed selects. The common pattern is a searchable BelongsTo where Nova's default dropdown becomes unusable:

SearchableSelect::make('Owner', 'owner_id')
    ->options(User::pluck('name', 'id'))
    ->displayUsing(fn ($id) => User::find($id)?->name)
    ->searchable()

If the package supports an AJAX/searchable() mode with a remote source, point it at a small JSON endpoint you control (/nova-api/users/search?q=) rather than letting the browser filter a giant payload. That endpoint should return [{ value, label }] and be scoped by the same authorization you use elsewhere — a searchable select is still a data-exposure surface.

Cascading / dependent selects. For "Country → Region → City," the reliable pattern is to make each downstream field's options() depend on the parent value from the request, and force a form refresh on change. If the package ships a JS hook (check the Vue component for emitted events like change/input), use it; otherwise, a Nova dependsOn() chain with server-side options is the least fragile approach.

Index and detail formatting. Searchable selects usually store the raw ID. Add ->displayUsing() or a matching BelongsTo presentation on the detail view so the index table shows a human label, not 42.

Validation. Treat the field like any other select: ->rules('required', 'exists:categories,id'). Do not rely on the field's client-side filtering as a constraint — a determined user can post any ID.

Integration tip: keep searchable selects off mass-assignment-critical forms unless you've confirmed the component posts a scalar value (not an array or object). Log $request->all() once in a test form to see exactly what ships over the wire.

Gotchas and Tips

The dependency risk is the headline gotcha. Zero dependents and a single release since June 2024 means no ecosystem has exercised this against Nova upgrades. Pin the version in composer.json, and consider a repositories entry pointing at a tag you've forked internally if you adopt it broadly. Budget for maintenance: you may become the de-facto maintainer.

Assets are the most common failure mode. A blank or unstyled field almost always means nova:asset wasn't run, the compiled JS in dist/ is stale, or the fork's webpack.mix.js/vite.config.js wasn't rebuilt. Check resources/js/ vs. what's actually served; if dist/ is committed and old, rebuild it yourself.

Nova version compatibility. Verify against your installed Nova major version (4 vs. 5 have different component scaffolding and asset pipelines). If the package's composer.json allows a Nova range you haven't tested, constrain it.

Search performance. Client-side filtering of ->options(User::all()) will be fine in dev and terrible in production. Move to a server endpoint with a LIMIT and a debounce as soon as the table exceeds a few thousand rows.

Label vs. value mismatch. If options() keys and values ever diverge (numeric string vs. integer IDs), selection silently fails to persist. Cast in pluck() explicitly: ->pluck('name', 'id') where id is an int.

Debugging path when it breaks: (1) field renders but no search → JS asset/component issue; (2) search works but value doesn't save → form request / displayUsing / cast issue; (3) saves but detail view blank → presentation, not the field. Isolate with a throwaway Nova resource before blaming your main form.

Extension points to inspect: the field class's resolveUsing/displayUsing methods, any published config file, and the Vue component's props — these are where a fork most often drifts from the original package's documented API. When the README and the code disagree, the code wins.

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.
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo