nova-custom/dynamic-action-modal
A Laravel Nova package for dynamic action modals, letting you build and trigger custom modal forms from Nova actions. Stars: 0. Score: 0.
Reality check first. This is a 0-star, 0-dependent, single-release (Dec 2021) package published under a nova-custom/* vendor namespace with a NOASSERTION license. Treat it as a fork or vendored snippet rather than a maintained dependency. Before writing a single line of feature code:
composer.json — confirm the require block. The stated php <= 7.3.0 constraint means it cannot be installed on PHP 8.x, which in turn rules out Laravel 9/10/11 and Nova 4/5. Realistically this only runs on Nova 3.x + Laravel 8.x + PHP 7.3.src/ — there is almost certainly one action class plus one or two field wrapper classes. That is the whole package.LICENSE / the license field. NOASSERTION means you have no explicit grant. If this is for a client project, get legal sign-off or copy the ~200 lines into your own app instead of depending on it."repositories": [
{ "type": "vcs", "url": "https://github.com/dejan-bjelajac/nova-custom-dynamic-action-modal" }
],
"require": {
"nova-custom/dynamic-action-modal": "dev-master"
}
Then composer update nova-custom/dynamic-action-modal and verify vendor/nova-custom/ contains the classes you expect.
Where to look first. The entry point is whatever class extends Laravel\Nova\Actions\Action (or Fields\ActionFields) inside src/. That class is what you will use inside your own Action's fields() method. Grep for dependsOn and resolveUsing — those two calls are the entire mechanism of any dynamic-action-fields implementation.
First use case. The canonical one: a "Refund Order" action where the amount field's default/max and the presence of a reason textarea change based on a type dropdown the user picks inside the same modal. Nova actions normally render one static field set per modal; this package lets you swap fields after the modal is open, without a page reload. If you have nothing like that in your app, you do not need this package — a static fields() method and a canSee() closure gets you 90% of the way.
Pattern 1 — Conditional field visibility inside an action modal.
Implement the action's fields() to return the dynamic wrapper instead of a plain array, and let the wrapper resolve per-request:
public function fields(NovaRequest $request)
{
return [
Select::make('Type')->options([...])->displayUsing(...),
// package-provided wrapper; exact class name per src/
DynamicField::make('Details')
->dependsOn('type')
->resolveUsing(function ($type) {
return $type === 'partial'
? [Number::make('Amount'), Text::make('Note')]
: [Textarea::make('Full explanation')];
}),
];
}
Pattern 2 — Dependent dropdowns (country → region).
The value of one select feeds the option list of the next. Because Nova re-sends the action modal payload on the dependency change, keep the resolver pure and fast — no N+1 queries per keystroke. Cache option lists (Cache::remember("regions:$country", 300, ...)) or hardcode small enums.
Pattern 3 — Defaults derived from the selected resource.
handle(ActionFields $fields, Collection $models) runs at execute time, so never trust that the dynamic fields shown were the fields submitted. Re-validate in handle() and use $this->actionNotAllowed() / early return for inconsistent payloads. This is the single most important integration tip: the dynamic UI is cosmetic, your server-side validation is the contract.
Pattern 4 — Reuse across actions.
Extract a private method returning the shared field set and call it from multiple fields() implementations. Do not subclass the package's classes — you will be pinned to its internals, and with one release and no maintainer there will be no upstream fix if Nova changes a signature.
Pattern 5 — Wrap it, don't scatter it.
Put one small App\Nova\Actions\Concerns\HasDynamicFields trait around the package so you can swap the implementation for your own in a day. Given the dependency hygiene here, that seam is worth the twenty minutes.
php <= 7.3.0 in composer.json (if interpreted literally by Composer's require) will refuse to install on 7.4 or 8.x, or composer update will fail with a conflict against Laravel/Nova. Workarounds are --ignore-platform-reqs (bad) or forking to relax the constraint (better, and you should read every file before doing so).nova.mix.js, Nova::script). A Dec-2021 package almost certainly targets Nova 3. On Nova 4 expect the JS to be unregistered or the modal to render blank — debug by opening the browser console and checking whether the package's compiled JS is even in the app.js/vendor.js bundle.dependsOn() does not match the field's attribute() — not its label. Same class of bug for ->rules() inside a dynamic resolver: rules defined in the resolver are not automatically used by Action::handle(), so declare validation again in rules() on the Action or withValidator().Select::options() with cached arrays.canSee still runs. Fields that are hidden by the dynamic resolver should also be guarded with canSee() / canRun() where permissions matter — the resolver is UI, not authorization.composer.json (not dev-master), and add a smoke test of your own that asserts fields() returns the expected classes for each branch of the resolver.Field::canSee(fn ($request) => ...) combined with Action::fields() already covers it, is supported, and adds zero dependencies. Reach for dynamic action fields only when the field set itself must change (variable number of fields, different types), which closures genuinely cannot express.DynamicField/DependentField class (e.g. another Nova package you already have). Duplicate class names across Nova packages are a classic source of "works locally, breaks in CI" asset compilation errors.Bottom line: the concept (dynamic fields in action modals) is genuinely useful and is a real gap in plain Nova. This particular implementation is a 2021-era, unlicensed, PHP 7.3-capped artifact with zero adoption. Read it, understand the ~200 lines, and either copy it into app/Nova with your own tests or build the same thing natively — do not take it on as an unexamined Composer dependency for anything you intend to maintain past this year.
How can I help you explore Laravel packages today?