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 Searchable Select Filter Laravel Package

fontech/nova-searchable-select-filter

A Laravel Nova filter package that turns select filters into searchable dropdowns. Instead of scrolling through long option lists, users can type to quickly find and pick filter values, making resource filtering faster and more usable in Nova admin panels.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a micro-package (5 stars, single maintainer) so the source is the documentation. Budget ten minutes to read src/ and resources/js/ before writing any filter — the public API surface is small and you will learn more there than from the README.

1. Install

composer require fontech/nova-searchable-select-filter

No vendor:publish is usually required for a filter component; if the README lists one, publish and commit the public/vendor/... directory so deploys don't depend on an extra build step.

2. Create a filter stub and swap the parent class

php artisan nova:filter StatusFilter

Then change the generated extends Filter to the package's base class (check src/ for the exact FQCN — typically something like Fontech\NovaSearchableSelectFilter\SearchableSelectFilter).

3. Implement the options method

use Fontech\NovaSearchableSelectFilter\SearchableSelectFilter;

class StatusFilter extends SearchableSelectFilter
{
    public function name(): string
    {
        return 'Status';
    }

    public function options(): array
    {
        return [
            'draft'     => 'Draft',
            'review'    => 'In Review',
            'published' => 'Published',
        ];
    }
}

4. Register it

public function filters(Request $request): array
{
    return [new StatusFilter()];
}

First use case: a status or country filter with more than ~15 options, where Nova's stock SelectFilter becomes a scroll-hunt. That is the only thing this package buys you — a type-to-filter dropdown — so reach for it when the option list is long and static enough to render client-side.

Implementation Patterns

Static enums. Map a PHP backed enum to the options array and let the search box handle the size:

public function options(): array
{
    return collect(OrderStatus::cases())
        ->mapWithKeys(fn ($c) => [$c->value => $c->label()])
        ->all();
}

DB-driven options. Because options are shipped to the browser in the filter payload, keep the query narrow — select only the two columns you need and cap rows:

public function options(): array
{
    return Client::query()
        ->orderBy('name')
        ->limit(1000)
        ->pluck('name', 'id')
        ->all();
}

For anything larger than a few thousand rows, this package is the wrong tool — you want an async/remote-search filter, not a client-side one.

Cascading filters. Dependent selects (country → city) are not supported out of the box; the option list is static per filter instance. The workable pattern is to read the sibling filter from the request inside options() and return an empty array when the parent is unset. That forces a page-level filter apply, but it keeps the UI honest:

public function options(): array
{
    $country = $this->request->input('country');

    return $country
        ? City::where('country_code', $country)->pluck('name', 'id')->all()
        : [];
}

Default selection. Set a default in the constructor rather than fighting the Vue component:

public function __construct()
{
    $this->withMeta(['value' => 'published']);
}

Query application. The package only supplies the UI. You still own apply():

public function apply(Request $request, $query, $value)
{
    return $query->where('status', $value);
}

Reuse across resources. Extract an abstract base filter in app/Nova/Filters/ that extends the package class and resolves options from a model + column pair, so each concrete filter is three lines.

Gotchas and Tips

Nova version compatibility is the real risk. Nova 4 runs Vue 2 and Nova 5 runs Vue 3; a filter component built against one will silently render nothing (or throw a Vue runtime warning) against the other. Check resources/js/components/ for Vue.extend (v2) vs defineComponent/<script setup> (v3) before assuming it works. With 5 stars and no recent commits, assume Nova 4 unless proven otherwise.

Compiled assets. If your deployment pipeline doesn't run npm build inside Nova, the filter's JS must be published and committed. A blank dropdown with no console error is almost always an unpublished asset, not a logic bug.

Search is client-side. Typing filters the already-loaded options() array — it does not query your database. Do not promise users "type to search all 50k customers" with this package; they will get 50k options serialized into the Nova bootstrap payload on every page load. Watch for slow Nova index pages and check the filter payload in the network tab first.

options() is called on every filter render. Cache expensive queries (Cache::remember(..., 300, ...)) and bust the cache from model observers, otherwise every Nova page hit re-runs the query.

Filter key collisions. Nova keys filters by class name; two filters with the same short name across resources will clobber each other in the query string. Set public $component and, if needed, override the key explicitly.

Debugging. There's no error surface — failures degrade to an empty select. Work in order: (1) confirm the component name in the class matches the registered Vue component, (2) open the browser console for Vue warnings, (3) dd($this->options()) to confirm the payload, (4) only then suspect the JS.

Extension points. Override the Vue component by publishing the package's JS and pointing public $component at your own file — that's the cleanest way to add multi-select, labels, or async search without forking. withMeta() is passed straight through to the component, so custom meta keys are a supported-ish escape hatch if you read the component source to see what it consumes.

Maintenance posture. No dependents and low activity means you are the maintainer for your fork. Vendor the published assets into your repo, pin the Composer constraint to an exact version, and keep a one-file fallback SelectFilter ready so a Nova upgrade doesn't block a release.

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.
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
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle