Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Calculator Action Laravel Package

osama-dev/filament-calculator-action

A Filament action that opens a calculator modal for numeric fields, letting users perform quick calculations and insert the result directly into forms. Useful for prices, quantities, discounts, and totals.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and make sure Filament's asset pipeline picks up its JS/CSS — this package ships a client-side (Alpine) calculator, so a missing asset publish is the number-one "nothing happens when I click" cause.

composer require osama-dev/filament-calculator-action
php artisan filament:assets          # or vendor:publish if the README asks for it
php artisan optimize:clear

Where to look first, in this order:

  1. The README's usage snippet — copy it verbatim before customising. The exact namespace differs between Filament v3 (Filament\Tables\Actions\Action / Filament\Forms\Components\Actions\Action) and v4 (Filament\Actions\Action), and this package supports both.
  2. src/ — one Action class plus a ServiceProvider. Thirty seconds of reading tells you the real method names, which is faster than guessing from the README.
  3. resources/views/ — the modal Blade view is where the Alpine component lives. This is the file you'll actually be editing/overriding.
  4. resources/js/ + dist/ — confirms whether arithmetic is Alpine or a compiled bundle (affects whether npm run build in your app matters).

First use case — put a calculator on a numeric form field. The canonical day-one win is an order/quote form where a user needs to work out a price, discount, or split and then type the result in. A button next to the field opens a modal, the user does the maths instantly (no Livewire round-trip per keypress), and "Apply" writes the result back into the field's state.

use OsamaDev\FilamentCalculatorAction\Actions\CalculatorAction; // verify namespace in src/

TextInput::make('unit_price')
    ->numeric()
    ->suffixAction(
        CalculatorAction::make('calc_price')
            ->modalHeading('Work out the price')
    ),

Get that working end-to-end — button renders, modal opens, result lands in the input — before touching any options. That validates install, assets, and state wiring in one shot.

Implementation Patterns

Write-back is the whole point, so decide the direction of data flow up front. There are three patterns, and they're not interchangeable:

Pattern A — apply to a target field. The action receives the result and pushes it into form state. Most packages do this server-side via the action's closure, which means one round-trip on "Apply" only (acceptable — the arithmetic itself stays client-side):

CalculatorAction::make('calc')
    ->target('unit_price')      // confirm the option name in src/

Pattern B — entangle and let Livewire sync on save. If the package exposes the Alpine state, bind it to the field with $wire.entangle so nothing hits the server until the form is submitted. Fastest, but the field looks "dirty" without a matching afterStateUpdated — which is usually exactly what you want.

Pattern C — pure read-only utility. No write-back at all: a calculator in a table header action or page header for the user to sanity-check numbers against the row they're looking at. Zero integration risk, genuinely useful for finance/ops dashboards.

Row actions for auditing line maths. A Tables\Actions\Action on an order-items table that opens the calculator pre-loaded with quantity × unit price lets a support agent verify a line without a spreadsheet. Pair it with ->modalDescription() showing the inputs so the operator knows what was pre-filled.

Prefill from current state. Always seed the calculator with the field's existing value rather than an empty display — otherwise users re-key numbers that are already on screen and you get drift between what they saw and what they applied.

Nested inside a larger action. Because the calculator is just an Action, it composes: put it in a ->modalFooterActions() of another action, or inside a custom ->form() on a slideOver. Watch the z-index (see Gotchas).

Server-side recomputation as the source of truth. For anything financial, treat the calculator purely as a UX nicety for entry, and recompute the authoritative total in a mutateFormDataBeforeSave() or model observer:

protected function mutateFormDataBeforeSave(array $data): array
{
    $data['total_cents'] = $data['qty'] * $data['unit_price_cents'];
    return $data;
}

This is the pattern that lets you safely ship the calculator at all.

Localisation hook. If the calculator formats with . for decimals, wrap the display and parse with your app locale, or keep the widget strictly numeric and format only on write-back.

Gotchas and Tips

Floating point will bite you. Client-side JS arithmetic is IEEE-754. 0.1 + 0.2 renders as 0.30000000000000004 in the display if the package doesn't round. For money, either configure a precision option (check src/ for one) or store cents as integers and divide only at the boundary. Never let a raw JS float land in a decimal(10,2) column via a server-side action — validate and round on the PHP side.

The computed value is untrusted input. The whole selling point is that the browser does the maths, which means a user can submit anything. Rules like ->rules(['numeric', 'min:0']) are mandatory, and any business constraint (total >= cost, discount ≤ 30%) must be re-checked server-side. The calculator is a keyboard shortcut, not a validator.

Reactive dependencies still round-trip. If the field the result lands in has ->reactive() or ->live(), or a sibling has ->afterStateUpdated(), applying the result triggers Livewire — so the "zero round-trips" claim only holds for the arithmetic, not for the write-back. Budget for that; don't promise users instant totals on a dependent field.

Assets are the usual failure mode. If the modal opens but the buttons are inert, the Alpine component didn't load: check php artisan filament:assets, confirm the package's views are registered in its ServiceProvider, and check the browser console for a missing 404 on the JS bundle. In production behind a CDN, re-run the asset command after every composer update.

Nested modals and z-index. Opening the calculator from inside another modal or a slideOver can render it behind the parent. Check whether the action supports ->modalWidth() and whether the package view teleports to body; if not, override the Blade view and add x-teleport="body" — the view is published specifically so you can do this.

Multiple instances on one page collide. Alpine component state keyed by a fixed name will share values between two calculators on the same form. Confirm the package scopes state by the action name/$id; if it doesn't, override the view and add x-data="{ ... }" with a unique key per instance.

v3 vs v4 namespaces. The form-field action (suffixAction/prefixAction), table row action, and page header action all live in different namespaces and the v4 reorganisation changed several. If the README example 500s with "class not found", you're on the other major version — check src/ rather than the docs.

Testing: Livewire tests click the action and assert the modal renders, but cannot exercise the JS arithmetic. Assert the action exists and the result-writing closure behaves (assertFormSet), and reserve browser/Dusk tests for the actual key-pressing flow. Don't let a green Livewire suite convince you the calculator works.

Dark mode and theming come free if the package uses Filament CSS variables; if it hand-rolls colours, you'll get a white modal in dark mode. Ten-second check: toggle the panel theme and open it.

When to skip this package. If you need unit-aware maths (currency conversion, tax brackets, tiered pricing), the arithmetic belongs in PHP where you can test it — a client-side widget will silently diverge from your backend rules over time. Use it for free-form "user does some sums", not for regulated calculations.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource