harrald/nova-combobox-filter
A Laravel Nova filter that adds a searchable combobox dropdown for filtering resource listings, letting users quickly pick from related records instead of scrolling long select menus.
Architecture fit. The package is a thin presentation-layer plugin that plugs into Nova's existing filter contract (options() for the option set, apply() for the query constraint). It introduces no data model changes, no API surface, no background jobs, and no new runtime services. Architecturally it is the lowest-risk category of dependency: a UI control that composes into Nova's index query. Fit is strong only where Nova is already the admin plane; it has zero value outside Nova and must not be positioned as a public-facing product capability.
Integration feasibility. Nominal effort is hours, not a sprint: composer require, optional nova:publish, then subclass a base filter and register it in a resource's filters(). The real work is verification, not wiring. Feasibility is gated almost entirely on (a) Nova major version compatibility and (b) whether Nova's native SelectFilter::searchable()->multiple() already covers the need on Nova 4+. If native parity holds, the correct TPM call is to delete the dependency before adoption.
Technical risk.
apply() can stop constraining after an upgrade — users then see unfiltered data they believe is filtered. No error is thrown, and every operator of that resource is affected.composer constraints (e.g. *) are a red flag to read before committing.resources/js produces the classic works-locally / dead-in-production dropdown unless the build is committed or run in CI.Key questions to close before commitment.
SelectFilter with searchable() and multiple() satisfy the requirement? (Highest-value finding.)require block actually support it?Stack fit. Laravel + Nova only, and Nova must be licensed and working. Before any code, read the package's composer.json require block against the installed Nova version and confirm the front-end toolchain (Nova 3 = Vue 2 + Mix; Nova 4/5 = Vue 3 + Vite). This is the single highest-risk step in the evaluation.
Migration path.
select filter (e.g. filter orders by product, tickets by tag, users by team).App\Nova\Filters\ComboboxFilter extending the vendor class and have all app filters extend that. Swapping to native or a hand-rolled component later becomes a one-file change instead of a sweep across resources.whereIn.composer.lock, commit any published compiled asset, and add a small feature test asserting apply() still constrains the query — the cheapest insurance against the silent-failure mode.->limit() caps on model-sourced options (target tens; hard cap around 200).Compatibility. Verify on a staging branch before wiring resources, and add "re-verify this filter" to the standing checklist for every Nova upgrade. Because failures are silent, a staging smoke check must exercise the full path — registration → component → request → PHP — not just page load.
Sequencing note on URL state. Filter values are encoded in the query string. Changing the value shape (single string → array) when replacing a native filter will desync saved bookmarks. Decide up front whether to migrate them or accept a one-time break, and communicate it.
Maintenance. Assume you own the code. The source and Vue component are small enough to read and, if the package goes stale, to re-implement in app/Nova/Filters in roughly 1–2 engineer-days. That is the honest build-vs-buy baseline: both sides are small, so prefer building if the package does not fit cleanly rather than fighting it. Pin versions and commit published assets so production does not depend on an external build.
Support. No upstream SLA, no dependents to surface regressions, single author. Ownership sits with the team that owns the Nova admin panel. Support burden is low but non-zero: the operational requirement is a documented upgrade checklist plus a regression test per filter.
Scaling. Two limits dominate:
apply() to a single whereIn. Joins and subqueries inside apply() interfere with eager loading and pagination and are not this package's job.This is not relationship-aware or async-search filtering; "search users and pick several across a million rows" is a different, harder problem requiring a server-backed endpoint or custom component. Scope it out explicitly.
Failure modes and mitigations.
| Failure | Symptom | Mitigation |
|---|---|---|
| Nova major mismatch | Dropdown renders, never emits a value | Verify on branch; re-verify at each Nova upgrade |
| Silent non-constraint | Users see unfiltered data believing it filtered | apply() regression test + staging smoke check |
| Asset never built | Works locally, dead/unstyled in production | Publish + commit compiled asset, or build in CI |
| Empty-selection ambiguity | Zero rows vs all rows, depending on driver | Decide, document in the filter class, and test |
| Bookmark URL shape change | Saved filters desync after migration | Migrate or accept and announce a one-time break |
| Option overload | Slow index pages on large option sets | ->limit() caps; avoid high-cardinality columns |
Ramp-up. Low. A Nova-fluent engineer can read src/ and resources/js/ and ship a pilot in a day. Keep the debugging path documented — registration → component → network request → apply() — so "the filter does nothing" resolves to a specific layer rather than a vague investigation. Budget the effort as internal-tooling leverage, not as product investment.
How can I help you explore Laravel packages today?