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.
Defining a bulk action
Section titled “Defining a bulk action”Extend BulkActionDefinition and implement definition() and handle(). The #[AsBulkAction]
attribute registers it.
use Illuminate\Support\Collection;use Lattice\Actions\ActionResult;use Lattice\Actions\BulkActionDefinition;use Lattice\Actions\Components\Action;use Lattice\Core\Attributes\AsBulkAction;use Lattice\Ui\Enums\Variant;
#[AsBulkAction('app.products.archive-selected')]class ArchiveSelectedProductsAction extends BulkActionDefinition{ public function definition(Action $action): Action { return $action ->label('Archive selected') ->variant(Variant::Danger); }
public function handle(Collection $records): ActionResult { $records->each(fn (Product $product) => $product->update(['status' => 'archived']));
return ActionResult::success(['archived' => $records->count()]) ->toast("Archived {$records->count()} products.", Variant::Success) ->reloadComponent('app.products'); }}definition() returns the same Action component as a single action, so labels, variants,
confirmation, and forms
all apply — including a ->lazyForm()
one, which fetches its schema together with the selection payload once the bulk action bar opens
it. handle() returns an ActionResult like any action.
$records is a reserved parameter name — declare it to receive the selected records, and add
FormData $data alongside it when the bulk action also collects a form: handle(Collection $records, FormData $data): ActionResult.
Attaching it to a table
Section titled “Attaching it to a table”Return bulk actions from a table’s bulkActions():
use 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.
How records are resolved
Section titled “How records are resolved”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.