outl1ne/nova-inline-text-field
Nova Inline Text Field lets you edit text values directly from the Laravel Nova resource index without opening a detail page. Click, type, save—fast inline updates for a smoother admin workflow.
Install and pin the fixed release. The 3.0.0 line shipped with a parent-class signature mismatch; 3.0.1 is the patch that makes it usable. Install ^3.0.1 and never let a lockfile resolve to 3.0.0.
composer require outl1ne/nova-inline-text-field:^3.0.1
Verify compatibility before anything else. Open vendor/outl1ne/nova-inline-text-field/composer.json and confirm the laravel/nova and php constraints cover your stack. This package's majors historically move in lockstep with Nova's, so a mismatch here is the most likely reason nothing renders.
Confirm the class name. The changelog refers to InlineText; check vendor/outl1ne/nova-inline-text-field/src/ once and note the exact FQCN (historically Outl1ne\NovaInlineTextField\InlineText) in your resource file. There is no config to publish, no migration, no service provider wiring beyond Nova's auto-discovery.
Where to look first. Not the README — the source. The package is one field class plus compiled front-end assets; reading the class takes two minutes and tells you exactly which Nova field it extends and which methods it overrides. That matters because everything below hinges on that inheritance.
First use case — pick a low-risk string. The canonical first target is a moderation or triage queue where an operator fixes one field per row: a title, a slug, an internal reference code, a short note. Take an existing resource and swap a single field:
use Outl1ne\NovaInlineTextField\InlineText;
public function fields(Request $request)
{
return [
ID::make()->sortable(),
InlineText::make('Title')
->rules('required', 'string', 'max:255')
->sortable(),
// ...
];
}
Then run the smoke test:
php artisan optimize:clear
Hard-refresh the Nova index (compiled assets are cached aggressively), click into a cell, change the text, tab or blur out, and confirm the row updates without a page reload. Check updated_at moved and that observers fired. If that works, you understand the package.
Replace, don't add. The intended pattern is a straight swap: wherever you had Text::make('Title') on an index, use InlineText::make('Title'). Adding it alongside Text gives you two editable columns for the same attribute and a confusing UX. Keep the detail form on a normal Text field so the inline input stays an index-only convenience.
Mirror your detail-form validation. This is the single most important habit. Inline editing is a second write path into the same column, and it does not inherit rules from your FormRequest or from the field on the detail screen. Copy the rules explicitly:
InlineText::make('Slug')
->rules('required', 'alpha_dash', 'max:120')
->resolveUsing(fn ($value) => $value)
->fillUsing(fn ($request, $model, $attribute) => $model->{$attribute} = strtolower($request->{$attribute}));
If the rules drift between the two paths, you get columns that pass validation in one screen and fail in the other — usually discovered by an operator, not a test.
Use resolveUsing / fillUsing for transformations, never override resolve / fill. This is precisely the class of bug 3.0.1 had to patch: the package overrode a parent method and drifted from the parent signature. If you subclass the field or override those methods yourself, you take on the same fragility across Nova majors. The callback hooks are the supported extension point — stay on them.
Pair it with Nova's existing controls. ->sortable(), ->onlyOnIndex(), and conditional visibility compose normally because the field is a Nova field:
InlineText::make('Internal Code')
->rules('nullable', 'string', 'max:64')
->sortable()
->onlyOnIndex()
->canSee(fn (Request $request) => $request->user()->can('updateInternalCode', $this->resource)),
Triage-queue workflow. The highest-value pattern is a filtered index — ?status=pending — where the operator's whole job is to correct one field per row and move on. This is where the click savings compound: no detail view, no save-and-back, no lost scroll position. Wire it as a lens or a filtered resource index and the field earns its dependency.
Two-path resources. If a resource is edited both inline (fast fix) and in full (deep edit), keep the detail form authoritative and the inline field deliberately narrow. Restrict inline editing to fields where "wrong but not catastrophic" is a tolerable transient state, and leave anything that cascades — foreign keys, status enums driving state machines, money — on the full form.
Authorization inherits from Nova. Inline saves go through Nova's standard update endpoint, so resource policies govern who can write. You do not need extra guarding — but you do need to prove it (see Gotchas). Model events, observers, updated_at, and audit packages all fire as they would for a normal update, because it is a normal update.
Fallback plan is three lines. If the package is abandoned or breaks on a Nova major, swap back to Text::make('Title') and revert Composer. Write that down somewhere so abandonment is a scheduling cost, not an incident.
Never install 3.0.0. It has a parent-class method-signature incompatibility that surfaces as a fatal error at resource registration — which takes down the entire index or detail view for that resource, not just one cell. A whole-page failure from a one-column convenience dependency is an ugly ratio. Pin ^3.0.1, and treat future majors as staging review items with a changelog read, not routine composer update traffic.
The whole-page failure mode is the thing to internalise. A field class that fails at registration is not a degraded cell — it's a 500 on the resource. Before promoting, load every resource that uses the field, not just the one you were testing on.
Explicitly test the view-only path. Create a test account with view but not update permission on the resource, log in, and try to inline-edit. Reasoning about policy inheritance is not testing it. If a view-only user can write through the inline input, you have a privilege escalation and the package is not usable until you've guarded it.
Validation gaps are silent. Nova's index tables are not forms — rules you set on the detail field do not automatically apply here. ->rules(...) on the InlineText field is a separate declaration. Test rejection paths: empty required, over-length, invalid characters. If a bad value saves, you've found the gap before an operator did.
Use resolveUsing/fillUsing, not method overrides. Restating because it's the actual bug that shipped: overriding resolve or fill puts you on the wrong side of Nova's parent-class contract, and the failure is a signature mismatch that only appears after a Nova upgrade. Callbacks are the stable surface.
Assets cache aggressively. After install or upgrade, php artisan optimize:clear plus a hard refresh. A stale compiled asset presents as "the field renders as plain text" and sends people debugging PHP when the problem is the browser.
Single-line only. This is a text input, not a textarea. Long-form content, markdown bodies, and anything requiring a rich editor belong on the detail form. If the column routinely holds more than ~120 characters, pick a different field.
No audit trail beyond what your model gives you. The package adds no change log, no per-field permissions, no bulk editing, and no concurrency control — last write wins. If you need "who changed this and to what," that comes from your existing audit package picking up the Eloquent update event. Don't let anyone assume the inline field provides it.
Trim and normalize on the way in. Inline inputs accumulate leading/trailing whitespace from tab-and-paste workflows. Normalize in fillUsing rather than adding a cleanup job later.
Keep it off the critical path. The correct framing: if this field breaks, editors fall back to the standard edit form and keep working. If your workflow has no fallback — for instance, the inline grid is the only editing surface — you've made a single-maintainer community package load-bearing, which is the one thing this dependency cannot support.
Watch the detail-form drift. Because the two write paths validate independently, the natural decay is that the detail form gets stricter over time and the inline field doesn't. Add a note on the resource pointing at both rule declarations, or the divergence becomes invisible until data quality suffers.
How can I help you explore Laravel packages today?