dillingham/nova-conditional-fields
Dillingham/nova-conditional-fields adds conditional logic to Laravel Nova forms, letting fields show, hide, or toggle based on other field values. Build smarter, less cluttered resources with reactive forms and fewer custom scripts.
Open the README first, then src/ — that is the whole documentation surface. This is a WIP package with no docs site, no tests, and a single tagged release from February 2019, so treat the source as authoritative rather than any blog post or this guide.
composer require dillingham/nova-conditional-fields
If the tagged release won't constrain against your Nova version, pin the branch:
composer require dillingham/nova-conditional-fields:dev-master
Nova field packages ship compiled JS. After install (and after every composer update that bumps the package), republish assets so public/vendor/ matches the PHP side:
php artisan vendor:publish --tag=nova-conditional-fields-assets --force
# or, depending on how the service provider registers it:
php artisan nova:publish
First use case — a "Reason for cancellation" textarea that should only appear when status is cancelled:
public function fields(Request $request)
{
return [
Select::make('Status')->options([
'active' => 'Active',
'cancelled' => 'Cancelled',
]),
// Whatever the package's wrapper is called — a Conditional field, a
// ->when()/->dependsOn() macro, or a trait — the shape is the same:
// wrap the dependent field and declare (field, value) conditions.
Textarea::make('Cancellation Reason')
->conditionalOn('status', 'cancelled'),
];
}
Verify the exact method name against src/ before copying that into a real resource. The package predates Nova's native conditional support, so its API is a thin client-side wrapper over Vue reactivity, not a server-side framework feature.
Treat conditions as presentation, not authorization. The pattern is: put the controlling field earlier in the fields() array, then attach the condition to the dependent field. Nova's field values are reactive on the Vue side, so the condition re-evaluates as the user changes the parent select/boolean without a round trip.
Chain conditions for multi-field gates. Where the package supports multiple conditions or a closure, prefer explicit pairs over a clever closure — closures get no server-side evaluation and can't be reused in rules():
Text::make('Refund Amount')
->conditionalOn('status', 'cancelled')
->conditionalOn('refundable', true),
Keep validation aligned with visibility. This is the single most important pattern. Hiding a field does not stop its rules from firing, and showing one does not make it required. Mirror the condition in rules():
public function rules(Request $request)
{
return [
'cancellation_reason' => $request->status === 'cancelled'
? 'required|string|max:1000'
: 'nullable',
];
}
Do this via rules(Request $request) on the resource rather than per-field rules(), since the per-field array is static.
Scope to the right surface. Conditional logic is usually only wanted on forms. Combine with onlyOnForms() / hideFromIndex() / hideFromDetail() so the wrapper doesn't leak into index and detail views where there is no reactive parent to read from and the field will simply render (or fail to render) statically.
Reuse the condition as a small helper. Once you have three fields gated on the same parent, extract a resource method (protected function isCancelled(Request $request): bool) and call it from fields(), rules(), and any Action confirmation logic. The package only solves the UI half; the helper keeps the three copies honest.
Actions and inline create forms. Action modals use the same field pipeline, so conditional fields work there too — but the controlling field must exist in that modal's field set. A condition referencing a field that isn't rendered in the current context will simply never resolve to true.
dependsOn() has been in Nova since 3.x, and showWhen() / hideWhen() arrived in 3.2. On any modern Nova install, prefer the built-in methods — they're maintained, documented, and battle-tested. Evaluate this package only if you're pinned to an old Nova 2-era codebase, or as a reference implementation to read.$request->all(). Always backstop with conditional rules() and, where the value matters, strip it in the model or a saving observer.php artisan view:clear && php artisan config:clear, then hard-refresh the browser. Confirm the file actually exists under public/vendor/.composer update can silently break the UI if it pulls a version whose assets were never published. Add the publish command to your deploy script after composer install, and consider --force.field.value reactively the way Nova's stock fields do, the condition will never re-trigger. Debug with Vue Devtools: inspect the field component's props and watch whether value updates on change.dependsOn collisions. Nova core and other packages also introduce dependsOn semantics. If a field ends up with two competing mechanisms, behaviour is order-dependent and confusing. Keep the conditional wrapper as the outer, single source of truth.resources/js/ — copy it into your own nova-components/ package, add the condition props you actually need, and drop the dependency. That is usually a half-day job and pays for itself the first time Nova upgrades.composer.json and commit the lockfile.How can I help you explore Laravel packages today?