simplesquid/nova-advanced-number-field
An advanced number field for Laravel Nova that adds flexible formatting, min/max limits, step controls, and locale-aware display to numeric inputs, making it easy to build polished, precise forms for prices, quantities, and other numbers.
What this is. A single Laravel Nova field class plus a compiled Vue component that extends Nova's native Number field with decimal precision, prefix/suffix unit labels, and consistent formatting across form, index, and detail views. MIT licensed, 11 stars, zero dependents, last release 2025-03-27. It is entirely admin-layer presentation — no domain logic, no migrations, no services.
Architecture fit. The package's architectural virtue is that it formats at render time and stores raw numbers. Nova sorts and filters on the underlying column, so adopting this cannot alter query behavior, API payloads, exports, or downstream consumers — provided nobody ever writes a formatted string ("$1,234.00") into the database. That constraint is enforceable by review, which makes the blast radius small and the adoption decision reversible. It belongs in the app that owns the Nova panel, not in a shared domain package.
Integration feasibility. composer require plus swapping Number::make(...) for the package's class, then verifying index/detail/form on one resource. Effort is hours per resource, not days. Two real friction points: Nova is a private Composer repo, so credential failures surface as generic dependency-resolution errors rather than auth errors; and the namespace must be confirmed from source, not inferred from the README.
Technical risk. Four items, in descending order:
^3.0 lets a routine composer update cross the platform floor in CI with no code change. Pin ^3.3 explicitly.Key questions.
Stack fit. Laravel + Nova only. It does nothing for APIs, PDFs, emails, exports, or imports. Adopt it as one view of a number, paired with a canonical formatter (Number::currency(...) or a money value object). If the admin panel and the invoice must agree to the cent, the shared formatter is the contract — the field config is not.
Migration path. Pilot, contain, then roll out:
^3.3, swap one existing Number::make on a price field in staging, verify index, detail, and form under Nova 5. If it doesn't render, stop — the marginal value is precision and units, not validation.app/Nova/Fields/MoneyNumber, QuantityNumber) that set the standard configuration. This is simultaneously de-duplication and fork insurance.decimals(2), step(0.01), prefix('$')), percentage (suffix('%'), max(100)), quantity (decimals(0), integer rule), read-only computed values — rather than one global number config.->rules(...). Client min/max/step are input affordances; rules are truth.Compatibility. Validate with composer why-not before assuming. The release notes state Nova 5 was added, not that Nova 4 was retained — verify explicitly if we're on Nova 4. After any Composer or Nova bump, run nova:publish and optimize:clear; stale compiled assets are the classic Nova failure, not a field-logic bug.
Sequencing. Ride the Laravel 12 / Nova 5 upgrade at near-zero marginal cost; never lead it. Safe parallel work that doesn't depend on the upgrade: building the local subclasses, aligning column precision and model casts, hardening server-side rules, and standardizing the shared formatter. Treat 3.2 → 3.3 as a breaking change for anyone still on Laravel 10 / PHP 8.1 and record that decision in the repo.
Maintenance. Small and stable — one PHP class, one compiled asset, no runtime services. The recurring cost isn't code churn; it's the manual UI regression pass on each Nova major and the discipline of keeping the version pinned. Both are calendar items, not backlog items.
Support. No vendor SLA, no commercial backing. The escalation path is "read the source, then fork." Document the contingency explicitly: pinned version in composer.json, most call sites pointing at our subclasses, and a written note that absorbing the class into app/Nova/Fields and dropping the dependency is an afternoon's work. That note is what converts "unproven dependency" into an acceptable decision.
Scaling. Effectively free. Formatting happens at render time with no additional queries; sort and filter performance is unchanged because we store raw numbers. Scaling cost tracks the number of Nova resources touched, which is a coordination cost across teams — not an infrastructure one. Keeping the field definitions centralized is what keeps that cost linear.
Failure modes to plan for.
nova:publish + optimize:clear, not PHP debugging.decimals(2) over a decimal(10,4) column means an operator saves 12.3456 and sees 12.35. Invisible until an accounting reconciliation. Make column, cast, and field agree.jsonSerialize() carries the config, the resource payload carries the component name, the component exists in published assets.Ramp-up. A Laravel developer is productive within hours; the debugging checklist above is the onboarding artifact. Budget one manual browser pass at rollout and one per Nova major thereafter. Assign a named owner for the pin, the subclass layer, and that regression pass — an unowned pinned dependency is the failure mode that actually bites.
How can I help you explore Laravel packages today?