ferdiunal/nova-editable-field
Nova Editable Field lets you edit Laravel Nova resource fields inline, directly from index and detail views, without opening the full edit form. A lightweight, configurable package that speeds up everyday data updates in your Nova admin panel.
1. Install into a Nova app
composer require ferdiunal/nova-editable-field
Nova's package auto-discovery registers the service provider. If the release ships compiled assets you may also need to publish them (check the README for the exact tag/provider — the repo is small, so the FieldServiceProvider in src/ is the authoritative source):
php artisan vendor:publish --tag=nova-editable-field-assets
php artisan nova:publish
2. Where to look first
README.md for the field class name and constructor signature (small package, 11 stars, 0 dependents — the README is the spec).src/ for the field class and its component() / resolve / fill behavior, especially whether it maps to Nova's stock Text or ships a custom Vue component in resources/js + dist/.composer.json for the laravel/nova constraint. This is the single most important line for upgrade planning.3. First use case — inline edit from the index table
The value proposition is editing a scalar column without opening the detail page: renaming a record, toggling a status label, editing a slug or sort order.
use Ferdiunal\NovaEditableField\NovaEditableField; // verify FQCN in README
public function fields(NovaRequest $request)
{
return [
ID::make()->sortable(),
NovaEditableField::make('Name')
->rules('required', 'max:255')
->sortable(),
// keep the read-only field for detail/forms
Text::make('Name')->onlyOnDetail()->onlyOnForms(),
];
}
Confirm it works before widening scope: open the index, click the cell, edit, blur/enter, and watch the Network tab for the PUT /nova-api/{resource}/{id} call. If that round-trip succeeds, the package is doing its job; everything after that is policy and validation.
Scoped to index only. Editable-in-place is a convenience for one or two columns. Reach for it on the index and leave everything else as normal Text/Select fields on the detail and form views, using onlyOnIndex() / onlyOnDetail() / onlyOnForms() to keep a single canonical field per attribute.
Pair it with a policy, not just rules. The save path goes through the resource's update endpoint, so the update policy ability is the real gate. If some rows must not be editable, express that on the field rather than duplicating logic in the component:
NovaEditableField::make('Status')
->rules('required', Rule::in(['draft', 'review', 'published']))
->canSee(fn ($request) => $request->user()->can('update', $this->resource))
Validation rules are not inherited. An inline editor with no ->rules() will happily persist garbage. Treat every editable field as a miniature form: required, max:, and Rule::unique(...)->ignore($this->resource->getKey()) where relevant. Unique rules without the ignore will fail on every save of the current record.
Keep the index query lean. The cell needs the raw attribute, so avoid displayUsing() on the same field — you'll either prefill the input with the formatted string or get a confusing mismatch after save. If you need a formatted read-only presentation elsewhere, use a separate display-only field.
Compose with the rest of the Nova surface. Sortable, hideFromDetail(), help(), and searchable index columns all still work; the field is only special in how it renders the index cell. Use it alongside nova-filterable-cards-style filters, metrics, and actions — the editable column is orthogonal.
Handle the post-save refresh. Most inline-edit implementations patch the row in place. If yours doesn't, listen for Nova's success event and call this.$router.go() or Nova.$emit('refresh-resources') in a small wrapper component, or simply accept a manual refresh — but decide this deliberately rather than discovering a stale row during a demo.
Testing pattern. Feature-test through Nova's API rather than the Vue layer:
$this->actingAs($user, 'web')
->putJson('/nova-api/users/'.$user->id, ['name' => 'New Name'])
->assertOk();
$this->assertDatabaseHas('users', ['id' => $user->id, 'name' => 'New Name']);
Also assert the negative: a user without the update ability gets 403, and an invalid value gets 422.
"ferdiunal/nova-editable-field": "~1.0" (or the exact tag) rather than *, and read the diff before bumping.$fillable/$guarded, model events and observers, and updated_at all fire as normal. A 403 from a mass-assignment guard looks like a generic toast in the UI — check storage/logs/laravel.log when a save "does nothing."fieldsForIndex? (2) does the compiled JS exist in dist/ and did you run php artisan nova:publish? (3) is the PUT request present in the Network tab with a CSRF token? (4) what does the 422/403 response body say? Turn APP_DEBUG on in a local environment — Nova swallows the underlying exception message otherwise.php artisan view:clear && php artisan nova:publish is the canonical "why is the old component still loading" fix.->component('your-component'), and the class is easy to extend since it's just a Nova field subclass. With MIT licensing and a tiny codebase, forking into your app's app/Nova/Fields is a legitimate risk-mitigation strategy if the package goes unmaintained — that's often cheaper than waiting for an upstream fix.How can I help you explore Laravel packages today?