gldrenthe89/nova-calculated-field
A Laravel Nova field that displays calculated values across index, detail, and form views. Supply a callback to derive results from other fields or model attributes without storing them in the database, keeping derived data accurate and in sync throughout your admin panel.
composer require gldrenthe89/nova-calculated-field
There is nothing to publish and no migrations — this is a Nova field, not a service provider with config. It only does anything inside a resource's fields() method.
As of v2.4.1 the package no longer declares laravel/framework as a requirement, so it now installs cleanly alongside Laravel 10/11/12 as long as your laravel/nova version supports it. If you previously hit a Composer conflict pinning you to an older release, this is the release that unblocks you.
Where to look first:
calculateUsing-style callback signature.vendor/gldrenthe89/nova-calculated-field/src/ — there is essentially one field class. Read it once and you know the whole package.First use case: a display-only "Total" on a resource form, computed from other fields so you don't need a database column or a model observer.
use Gldrenthe89\NovaCalculatedField\CalculatedField; // confirm exact class in README
public function fields(NovaRequest $request): array
{
return [
Number::make('Price'),
Number::make('Quantity'),
CalculatedField::make('Total')
->calculateUsing(fn (array $values) => ($values['price'] ?? 0) * ($values['quantity'] ?? 0))
->exceptOnForms(), // if you only want it shown, not submitted
];
}
Keep the formula in one place. The single biggest maintenance cost with calculated fields is the same formula drifting across fields(), fieldsForIndex(), lenses, and a resolveUsing somewhere. Put the formula in a static method or a small Calculator class, and have the Nova field call it:
// app/Nova/Support/InvoiceTotals.php
public static function total(array $values): float
{
return round(($values['price'] ?? 0) * ($values['quantity'] ?? 0), 2);
}
Then both the Nova field and any unit test use InvoiceTotals::total(). The Nova field becomes wiring, which is the part you can't easily test anyway.
Index vs detail. Compute on the detail/form view where the user is actually editing inputs. On index pages, if the value is expensive (relationships, aggregates) you're better off persisting it — see below — or guarding with ->onlyOnDetail().
If you need sorting or filtering, persist. Calculated fields are display-time; they are not sortable or filterable over the database. If a user asks "sort by total", the answer is a real column updated in a model event/observer (or a DB generated column), not a tweaked calculated field. Trying to bolt ->sortable() onto a computed value is the classic dead end here.
Reuse through a factory method rather than copy-pasting the field definition — a MyFields::invoiceTotal() helper keeps the callback, formatting (->displayUsing(), currency helpers from Nova's own field API), and visibility flags consistent across resources.
Test the formula, not the field. Unit-test the calculator class. Only reach for Nova's HTTP/feature testing if you've genuinely got custom field logic.
composer update gldrenthe89/nova-calculated-field --with-dependencies, then php artisan optimize:clear. No JS rebuild is needed on your side, but cached Nova assets occasionally mask a version change — a hard refresh fixes "it didn't update."laravel/framework actually means: the package now inherits the framework version pulled in by laravel/nova. Your app's composer.json must still require laravel/framework; don't infer from this release that you can drop it. And if you maintain a fork or run the package's own test suite in CI, check that require-dev still has the framework — a test bootstrap with no framework installed fails in confusing ways.$values['price'] can be missing entirely on first render. Always ?? 0 / null-guard, otherwise the create form throws before the user types anything.canSee()/->hide() may not appear in $values at all, so $values['x'] raises an undefined-key warning rather than returning null. Same guard fixes both.19.999999999. Work in integer cents or use bcmath inside the formula, then format for display.indexQuery() or keep computed fields off the index.How can I help you explore Laravel packages today?