Actions
Datatables have actions that can be applied to the selected rows.

Setting up actions
Actions are described by an array, usually built by a class that extends Medialight\Textstem\Actions\ActionBuilder. Set the result as the table's $actionconfig in mount():
public function mount()
{
$this->actionconfig = (new TrackActionBuilder)->collect();
$this->filterconfig = (new TrackFilterBuilder)->collect();
parent::mount();
}
textstem:make:module generates both builders in app/Domain/{Module}/Config/. A builder looks like this:
<?php
namespace App\Domain\Tracks\Config;
use Medialight\Textstem\Actions\ActionBuilder;
use Medialight\Textstem\Contracts\CollectsActionsConfig;
class TrackActionBuilder extends ActionBuilder implements CollectsActionsConfig
{
public function collect()
{
$actions = [
'set' => [
'label' => 'Set ... ',
'action' => 'set',
'input' => 'select',
'options' => [
'enabled' => [
'input' => 'select',
'options' => [
['label' => 'Yes', 'value' => 1],
['label' => 'No', 'value' => 0],
],
],
'genre' => [
'input' => 'select',
'options' => ['rock', 'jazz', 'folk'],
],
],
],
'tag' => [
'label' => 'Add tags',
'input' => 'text',
],
'delete' => [
'label' => 'Delete',
'action' => 'delete',
],
];
return $this->prepare($actions);
}
}
prepare() fills in a missing name (the array key) and label, formats options the same way as select options in the page builder, and picks an input for entries that don't name one.
What the actions do
The base Table runs three actions for you:
| Action | Does |
|---|---|
delete |
Deletes each selected row |
set |
Sets the chosen attribute (the key under options, such as enabled) to the chosen value on each row |
tag |
Attaches the comma-separated tags typed in, on models that use tags |
For anything else, override runResourceBulkAction() in your table. Return true when you've handled the action, or false to fall through to the built-in ones:
protected function runResourceBulkAction(?string $name, string $target, mixed $value, $models): bool
{
if ($name === 'archive') {
$models->each->update(['archived_at' => now()]);
return true;
}
return false;
}
Checks before an action runs
Livewire requests don't pass through route middleware again, so the table checks every action itself:
- the user must pass
access-textstem-admin; - the action, its target and its value must be ones listed in
$actionconfig; a value for aselectmust be one of its options; - if the model has a policy, the user must be allowed to
update(or, fordelete,delete) every selected row.
Anything else is refused with a 403. Register a policy for your own models (see Authorisation), or these checks fall back to the admin gate alone.