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

Batch Edit Toolbar Laravel Package

digital-creative/batch-edit-toolbar

A Laravel Filament package that adds a batch edit toolbar to tables, letting users select multiple records and update shared fields in bulk. Streamline admin workflows with inline bulk editing directly from the resource list.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a Laravel Nova add-on, not a general Laravel package. If you are not running Nova, stop here — there is nothing to leverage. Confirm your Nova version first; the last release (Oct 2023) predates Nova 5, so verify compatibility before committing.

composer require digital-creative/batch-edit-toolbar

No publish step is typically needed — the provider is auto-discovered and the package is intentionally thin. Look first at: the README snippet (the API surface is one class and a handful of fluent methods), then src/BatchEditToolbar.php if the README is ambiguous. With 8 stars and 0 dependents, the source is the documentation — read it before debugging behaviour, and vendor/patch it if needed rather than waiting on an upstream fix.

First use case — publishing many records at once:

use DigitalCreative\BatchEditToolbar\BatchEditToolbar;

public function fields(NovaRequest $request): array
{
    return [
        BatchEditToolbar::make()
            ->addFields([
                Select::make('Status')->options([
                    'draft'     => 'Draft',
                    'published' => 'Published',
                ])->rules('required'),
            ])
            ->onlyOnIndex(),

        ID::make()->sortable(),
        Text::make('Title'),
        Select::make('Status')->options([/* ... */]),
    ];
}

Select rows in the index (or "select all"), click the toolbar, fill in the single field you configured, submit. The package applies that value to every selected resource. Keep the toolbar to one column per toolbar — that is the design intent per the description, and it keeps validation and the authorization story simple.

Implementation Patterns

One toolbar per concern. Rather than one giant toolbar, add focused toolbars: a "Publish" toolbar for status, an "Assign owner" toolbar for user_id. Each is cheap and the UX is much clearer than a modal with five unrelated fields.

Share via a trait or base resource. In a multi-resource app, define the toolbar factory once:

trait HasBatchStatusToolbar
{
    protected function batchStatusToolbar(): BatchEditToolbar
    {
        return BatchEditToolbar::make()
            ->addFields([
                Select::make('Status')->options(static::statusOptions())->rules('required'),
            ])
            ->onlyOnIndex()
            ->canSee(fn (NovaRequest $request) => $request->user()->can('publish', static::newModel()));
    }
}

Gate it with policies. The package runs through Nova's request lifecycle, so the resource's update ability and any canSee/canRun guards apply. Add an explicit ->canSee(...) for privileged columns (pricing, ownership) — do not rely on the field merely not being displayed.

Pair with Nova search/filter for targeting. The realistic workflow is: filter to "draft + category X", select all, publish. Because the toolbar honours whatever index query is active, users batch-edit sets, not tables. Document that in your UI.

Let model events do the heavy lifting. Each selected model is saved individually, so updated observers, activity logs, and audit trails fire normally. Put side effects (Slack notification, search reindex, cache bust) in the observer rather than in the toolbar config — that keeps batch edits and single edits behaving identically.

Combine with conditional containers (digital-creative/nova-conditional-container) inside the toolbar's field list if a field only makes sense for some states, e.g. a "publish at" DateTime that appears when status === published.

Gotchas and Tips

  • Compatibility is the real risk. Last release Oct 2023, 8 stars, 0 dependents. Pin the version in composer.json, and smoke-test batch edit against your Nova version after every Nova minor upgrade. If it breaks, expect to fix it yourself.
  • onlyOnIndex() is mandatory. Nova fields are shared across index/detail/create/update. Without it, the toolbar (and its modal fields) will surface on forms where it makes no sense.
  • Toolbar fields are not index columns. Declaring Select::make('Status') inside the toolbar does not render a Status column. Declare the display field separately in fields().
  • File/Image fields will not work. Uploads need Nova's file-handling request context, which the batch path does not provide. Stick to scalar columns: Text, Number, Select, Boolean, Date, Textarea, BelongsTo (test it).
  • Relationship fields need verification. BelongsTo saving depends on Nova's saveRelationships behaviour; if the toolbar calls fill()/save() directly, foreign keys may not be set the way they are in the resource form. Verify with a BelongsTo before shipping, and fall back to a raw Select::make('user_id') keyed by ID if it misbehaves.
  • No transaction around the batch. With N selected rows there are N individual saves; a failure mid-way leaves you partially updated. Keep validation rules strict on the toolbar fields (so failures happen before any save), and for bulk operations that must be atomic, wrap the concern in a Nova action instead — actions give you explicit handle(ActionFields, Models) with a transaction.
  • Performance degrades linearly. "Select all" over thousands of rows means thousands of saves and observer calls. Cap selection in practice (filter first), or move true bulk updates to a queued action.
  • Validation lives on the field. ->rules('required') works because Nova evaluates the field rules server-side; a failed rule surfaces as a modal error and blocks the update. Use ->rules() rather than controller-level validation you can't hook into.
  • Debugging: open the browser network tab and inspect the Nova request triggered by the toolbar's submit — it reveals the endpoint and payload, which is far faster than reading the package source. laravel/telescope will show the per-model updates.
  • After a batch edit, refresh the index. The table does not always reflect the new values immediately, and stale UI has caused more than one "the package is broken" false alarm.
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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels