outl1ne/nova-multiselect-field
Laravel Nova multiselect field with searchable multi- and single-select, async resource querying, drag-and-drop reordering, option dependencies, distinct value groups, and on-the-fly tagging. Stores values as JSON and supports light and dark modes.
Architecture fit
Select field contract. It stores selections as a stringified JSON array in a text-based column by default, or as native JSON via saveAsJSON() when the DB column is a JSON type.NovaMultiselectDetailFieldValue, FormFieldTag), so branding/UX can be tailored without forking.asyncResource, api), option groups, dependency between fields (optionsDependOn), distinct option pools, taggable, reorderable, and belongsToMany / belongsTo relationship modes.Integration feasibility
composer require outl1ne/nova-multiselect-field; no migrations, service-provider wiring, or asset build step required.Select API. A TPM can reasonably scope this as a same-sprint deliverable for a competent Laravel dev.app.js, which is standard Nova practice.Technical risk
php: ^8.1 and laravel/nova: ^5.0; older Nova majors live on separate maintained branches (v4, v3). This forces a coordinated upgrade whenever Nova ships a breaking major.saveAsJSON() only helps if the schema is already JSON-typed. This leaks into reporting, exports, and any downstream service reading the column.Dependents: 0 signal is expected for a leaf Nova field (apps consume it, not packages) but should not be read as proof of adoption — validate against our own repo scan.2026-06-10) is in the future relative to typical evaluation windows. Treat as a metadata error until confirmed against Packagist.OptimistDigital\… → Outl1ne\… in v4) is a precedent that the package has already forced a breaking rename once; plan for similar churn.Key questions
saveAsJSON) or legacy text/varchar? Who else reads those columns?belongsToMany — will we enforce belongsToMany(..., false) only on bounded tables?distinct/optionsDependOn UX map to real business rules, or are we inventing complexity?Stack fit
belongsToMany.taggable() would create ungoverned values, or any surface needing SQL-level analytics on the selection.Migration path
composer require, publish translations (optional), declare fields in Resources, choose storage type per column.Select/native relation fields to Multiselect one resource at a time; watch for value-shape changes (single string vs JSON array) and backfill existing rows to the stringified array format.^5.0 branch supports the fields in use; if stuck on Nova 4, pin the nova-v4 branch explicitly rather than relying on Composer resolution.Compatibility
^8.1 and Nova ^5.0 are explicit gates; older Nova requires branch pins. No reported peer conflicts beyond that.app.js components before the package itself breaks.Sequencing
options() first; add asyncResource / belongsToMany only where bounded.distinct, optionsDependOn, taggable) after the pilot validates UX and data shape.Maintenance
Support
Scaling
asyncResource, custom api) is the correct pattern for large tables; optionsLimit (default 1000) caps render cost.belongsToMany(..., false) eager-loads all options — enforce a bounded-row rule or accept admin page latency.indexValueDisplayLimit / indexCharDisplayLimit; set these deliberately to avoid slow list views.Failure modes
saveAsJSON() enabled on a non-JSON column (or vice versa) silently corrupts reads.belongsToMany without async on a large table degrades the admin.optionsDependOn leaves orphaned values when the parent field changes; needs validation rules.taggable values: free-form tags drift from the canonical taxonomy.api endpoints: auth/tenant scoping must be enforced server-side; the package only passes a search param.Ramp-up
belongsToMany with copy-paste examples.How can I help you explore Laravel packages today?