outhebox/nova-hidden-field
A Laravel Nova field that hides attributes from forms and detail views while still submitting and storing their values. Declare defaults for auto-filled or sensitive data, keep the UI clean, and persist values without custom JavaScript or resource workarounds.
Install it alongside Nova and confirm it actually works on your Nova major before you build anything on top of it:
composer require outhebox/nova-hidden-field
There is no config to publish, no migration, and no asset build step — the service provider is auto-discovered. The entire package is one PHP field class (src/Hidden.php) plus a trivial Vue component. Read both once; that is your whole dependency surface.
The gating step is compatibility. The last release was 2020-05-20, predating Nova 4 and 5, and laravel/nova is not on Packagist, so Composer cannot block an incompatible install. Prove it first: drop the field into a resource, load the create form, and check that (a) the browser console shows no "unknown component" warning and (b) an <input type="hidden"> is present in the DOM with your default in it. If either fails, stop and write the field in-house — it is roughly 30 lines.
The first real use case is a column a human should never choose — user_id, tenant_id, created_by, source:
use Outhebox\NovaHiddenField\Hidden;
public function fields(Request $request)
{
return [
ID::make()->sortable(),
Text::make('Title'),
Hidden::make('User ID')->default(auth()->id()),
];
}
Because it renders as a normal hidden input inside the Nova form, the default rides along with the standard create/update request. No custom controller, no fillUsing for the simple case.
Create-time stamping. Hidden::make('User ID')->default(auth()->id()) is the canonical shape. Add ->rules('required', 'exists:users,id') when a missing value would corrupt data, so it fails loudly instead of silently writing null.
Ambient request data. Anything the request can see is fair game: ->default(request()->ip()), ->default(request()->header('X-Campaign')), ->default(session('affiliate')). This is where the field beats a model event — the value travels with the Nova form submission rather than being reconstructed server-side.
Carry a computed key for a visible field. Store Str::slug($request->input('title')) in a slug column while the editor only touches the title. The hidden field keeps the value in the payload so it is set on create without a separate endpoint.
Recompute on every save with fillUsing(). ->default() only applies when the field has no existing value, so on edits the stored model value wins. When a value must be refreshed each save:
Hidden::make('Updated By')
->default(auth()->id())
->fillUsing(fn ($request, $model) => $model->updated_by = auth()->id());
Per-operation resources (Nova 4+). Prefer fieldsForCreate() / fieldsForUpdate() over branching inside one fields() method, and attach the hidden field only where it has a job. Keeps the update path clean.
Keep it off index and detail. Verify it is suppressed on index/detail; if it shows up as a blank column, chain ->hideFromIndex() / ->hideFromDetail() explicitly.
Group attribution metadata. Several hidden fields in one resource (source, campaign, referrer) is a cheap way to capture attribution without a custom Nova tool — all the logic stays readable in one fields() method.
Validation is the real contract. A hidden input is still client-supplied and trivially editable through devtools. Treat ->rules() as the authoritative check, and derive anything security-sensitive server-side in fillUsing() rather than trusting a posted default.
->hideFromCreate(), ->onlyOnDetail(), ->hideWhenCreating()), Nova never mounts the component, so ->default() never reaches the request and the column ends up null. Hidden does not mean omitted — the value needs a rendered hidden input to be submitted at all.->default() does not overwrite on update. The most common surprise for developers coming from model events. Use ->fillUsing() or a saving model event when the value must be recomputed every save.nova:run commands, imports, seeders, and direct API writes never touch the field. Keep authoritative logic in the model or a service; treat this as a convenience for the Nova UI path only.->rules('required') on a hidden field bites in non-UI paths. Validation fails on any request where the component did not render — a classic "why is this action erroring?" bug. Prefer sometimes / nullable unless you have confirmed every render path.Hidden::make(...) for Text::make(...) (or add ->showOnDetail()) to see whether the default is actually populated. Dump $request->all() in a throwaway fillUsing closure to confirm the field is in the payload. If it is missing, the component did not mount — check the console for a registration warning.Field chain (fillUsing, resolveUsing, withMeta) or by forking the class. There is no conditional visibility here — despite the description, this is a hidden input, not a reactive show/hide engine. If you need conditional fields, you are writing that yourself.booted() / saving on the model and use the hidden field only for UI conveniences where a missing value degrades gracefully.How can I help you explore Laravel packages today?