merotech/appendable-dynamic-dropdown
A Laravel package for building appendable, dynamic dropdowns whose options load and update on the fly. Add reusable select fields to your forms, wire them to server-side data, and let users append new choices without page reloads.
merotech/appendable-dynamic-dropdown is a Laravel Nova form field that fuses a <select> with a free-text input: users pick an existing related model from a dropdown, or type a new value that gets appended (and typically created) on the fly. Because the repo is archived and has essentially no public usage, treat your first hour as a compatibility check, not a productivity win.
Minimal steps:
composer require merotech/appendable-dynamic-dropdown then immediately check composer.lock and the package composer.json for laravel/nova version constraints. If it only lists Nova ^4 and you run Nova 5, stop and read the source before going further.dist/ bundle that must be published (php artisan vendor:publish --tag=nova-assets or nova:publish) and then compiled by Nova's own asset pipeline. If the field renders as a blank row or an unstyled input, missing assets are the first suspect.src/ (its component property and any ->options() / ->appendable() / ->createOptionUsing() style fluent methods) and the matching resources/js/components/*.vue. The public API is defined there, not in the (likely thin) README.belongsTo relationship on a Nova resource where the related table is a small, user-maintained lookup — categories, tags, departments, sources. Example shape (verify method names against the source):use Merotech\AppendableDynamicDropdown\AppendableDynamicDropdown;
public function fields(Request $request)
{
return [
AppendableDynamicDropdown::make('Category', 'category_id')
->options(Category::orderBy('name')->pluck('name', 'id'))
->searchable()
->appendable(),
];
}
Lookup-table editing in place. The dominant pattern is a belongsTo field where the related table is curated by the same admins filling out the form. Wire the field to ->options(Model::pluck('name', 'id')) and let the append action create the missing row. Keep the foreign key column nullable or have the append callback return the new ID synchronously — otherwise Nova saves null.
Dynamic options from a scoped query. Because options are computed in the field definition, use $request or dependsOn to narrow the dropdown per context (e.g. categories filtered by a selected department). Remember ->options() is evaluated server-side once per request, so per-tenant scoping works cleanly but reactive filtering requires a dependsOn + resolveUsing combination and re-fetching.
Remote search for larger tables. If the underlying table grows past a few hundred rows, avoid loading everything into options(). Most appendable-select implementations expose a search endpoint or accept a Closure; confirm whether this package supports it, otherwise subclass the field and override the option-loading logic.
Standardise with a helper. Since the package is unmaintained, wrap it once:
class AppendableLookup extends AppendableDynamicDropdown
{
public function __construct($name, $attribute = null, $model = null)
{
parent::__construct($name, $attribute ?? Str::snake($name).'_id', $model);
$this->searchable()->appendable();
}
}
Then use AppendableLookup::make('Category')->options(...) across resources. This gives you a single place to patch if Nova or the package breaks — critical for an archived dependency.
Validation on append. Whatever callback creates the record (->createOptionUsing() or an equivalent), it should run Validator::make(...)->validate() and return the new key. Don't trust the front-end to enforce uniqueness or max length; the append flow bypasses your Nova rules unless you replicate them in the callback.
Integration tip for non-Nova forms. This is a Nova field, not a generic Laravel form component. If you also need appendable selects in Blade/Livewire, don't try to reuse this; you'll spend more time extracting the Vue component than wiring Select2 + tags: true fresh.
component against a current Nova field and confirm it renders on your Nova version. Pin the commit in composer.json ("merotech/appendable-dynamic-dropdown": "dev-main#<sha>" via a VCS repository entry) so a deletion of the repo doesn't break CI.php artisan nova:publish again after any Nova upgrade. If the package predates your Nova version's asset pipeline (Mix vs Vite), you'll need to rebuild dist/ yourself from resources/js.belongsTo shows as "no relation saved" — the form looks fine, the column stays null. Dump $request->all() in store() to see what actually posts.canCreate. If it doesn't, add an authorize()/canSee guard or wrap the create callback in Gate::allows('create', Category::class).QueryException by re-fetching the existing row. Add the unique constraint; don't rely on the dropdown to dedupe.mounted/mounted-adjacent methods for render issues and in the field class for option/append issues. Nova::dump() or a temporary ->help() with the raw options array is faster than reading the bundle.component, publish the Vue component if the package registers a publish tag, and treat any createOption* callback as the supported place for domain logic — that's the seam least likely to break if you later swap the package for a maintained alternative.AppendableLookup.How can I help you explore Laravel packages today?