Skip to content

Bulk actions

A bulk action runs over the rows selected in a table. It works like a regular action, except handle() receives the selected records as a collection.

Extend BulkActionDefinition and implement definition() and handle(). The #[AsBulkAction] attribute registers it.

use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Lattice\Lattice\Actions\ActionResult;
use Lattice\Lattice\Actions\BulkActionDefinition;
use Lattice\Lattice\Actions\Components\Action;
use Lattice\Lattice\Attributes\AsBulkAction;
use Lattice\Lattice\Core\Enums\ButtonVariant;
use Lattice\Lattice\Core\Enums\Variant;
#[AsBulkAction('app.products.archive-selected')]
class ArchiveSelectedProductsAction extends BulkActionDefinition
{
public function definition(Action $action): Action
{
return $action
->label('Archive selected')
->variant(ButtonVariant::Destructive);
}
public function handle(Collection $records, Request $request): ActionResult
{
$records->each(fn (Product $product) => $product->update(['status' => 'archived']));
return ActionResult::success(['archived' => $records->count()])
->toast(Variant::Success, "Archived {$records->count()} products.")
->reloadComponent('app.products');
}
}

definition() returns the same Action component as a single action, so labels, variants, confirmation, and forms all apply. handle() returns an ActionResult like any action.

Return bulk actions from a table’s bulkActions():

use Lattice\Lattice\Actions\Components\BulkAction;
public function bulkActions(): array
{
return [
BulkAction::use(ArchiveSelectedProductsAction::class),
];
}

When at least one row is selected, the table shows a bulk action bar.

The collection passed to handle() is resolved by the table’s data source — both an explicit set of checked rows and “select all matching”, which re-runs the current filters on a signed endpoint. With the Eloquent source this needs no extra code: the records arrive as models, ready to act on.