pavloniym/nova-options-selector
A Laravel Nova field package for adding an options selector to your admin panel, letting you choose from predefined option lists within Nova forms and resources.
pavloniym/nova-options-selector is a Laravel Nova 4 field that renders a searchable options dropdown — essentially an upgraded Select for long option lists (countries, timezones, statuses, categories) where the stock Nova select becomes unusable.
Minimal setup:
composer require pavloniym/nova-options-selector
There is typically no config file, migration, or asset publishing step — the field registers itself via the class import. The current release line (v1.1.2) targets Nova 4 and was specifically re-styled against Nova v4.34.3; verify the composer.json constraint against your Nova version before installing, and skip this package entirely if you are still on Nova 3.
First use case — drop it into a resource exactly where you would have used Select:
use Pavloniym\OptionsSelector\OptionsSelector;
public function fields(Request $request)
{
return [
OptionsSelector::make('Status', 'status')
->options([
'draft' => 'Draft',
'review' => 'In Review',
'published' => 'Published',
])
->searchable()
->rules('required'),
];
}
Look first at: the field's options() signature, whether your Nova version matches the 4.34.x baseline the CSS was built for, and the README's notes on searchable() / nullable() / multi-select support — those are the three flags that drive 90% of real usage.
Single source of truth for options. The most common day-to-day failure is options drifting between the field, validation rules, filters, and index display. Centralize them:
// app/Support/StatusOptions.php
public static function all(): array
{
return ['draft' => 'Draft', 'review' => 'In Review', 'published' => 'Published'];
}
Then reuse in the field, in ->rules('in:'.implode(',', array_keys(StatusOptions::all()))), and in any Nova filter.
Enum-backed options (Laravel 8.1+). Cleanest pattern for domain state:
OptionsSelector::make('Status')
->options(collect(Status::cases())
->mapWithKeys(fn ($c) => [$c->value => $c->label()])
->all())
->rules('required', Rule::enum(Status::class));
Readable index/detail columns. Nova will render the raw stored key on the index by default; map it back to the label:
OptionsSelector::make('Status')
->options($options)
->displayUsing(fn ($value) => $options[$value] ?? $value)
->onlyOnForms(); // or keep visible and rely on displayUsing
Pair with a matching Nova filter. Keep the filter's option keys byte-identical to the field's keys so the filtered URL and the stored column agree:
public function options(Request $request)
{
return StatusOptions::all();
}
Wrapping the field. Because this package ships visual-only patches (see v1.1.2), wrap it once so a future Nova restyle or package bump doesn't require touching every resource:
class StatusField extends OptionsSelector
{
public function __construct($name, $attribute = null, $resolveCallback = null)
{
parent::__construct($name, $attribute, $resolveCallback);
$this->options(StatusOptions::all())->searchable()->rules('required');
}
}
Integration tips. For multiple()-style usage (if supported in your installed version — confirm in the README), cast the column to array/json on the model and add ->rules('array') plus per-item in: validation. For dependent dropdowns, either use the package's dependency hooks if present or fall back to a custom field with dependsOn, since generic option-closure reloading is where these fields most often need hand-rolling.
composer.json and the open issues before committing this field to a resource used across multiple Nova versions.value => label. Validation in: rules, filter option arrays, and displayUsing maps must all use the keys, not the labels.'01', '1' array keys to integers; strict in: rules and === comparisons will then fail against strings stored in the DB. Prefix or cast deliberately for zip codes, years, or codes with leading zeros.->nullable(), clearing the selection may be blocked or store an empty string instead of null. Decide which your column allows and test the "clear and save" path explicitly — it is the most commonly missed edge case.displayUsing/resolveUsing callbacks are the stable seams. Prefer them over editing vendor assets or publishing/overriding the package's compiled styles — style overrides will be overwritten by the next Nova-alignment patch anyway.How can I help you explore Laravel packages today?