Moves and events
What happens on a drop
- The card moves in the browser at once, the column counts change, and the card is marked as pending.
- The browser asks the server (
kanbanMove, a renderless Livewire call: nothing is re-rendered). - The server loads the record through the board's
query()and checks the rules: both columns are visible to this user, the source isdraggable, the target isdroppable,acceptsthe source, and is not at its WIP limit. - Your move logic runs (by default: set the column attribute and save).
- The server answers with the card as it looks now; the card flashes once. If anything refused the move, the card slides back and the reason is shown as a notification.
"Move to…" in the card's menu does the same without dragging, for touch screens and keyboards.
Your own move logic
moveUsing() replaces the default save. Throw to refuse the move: the card goes back and the exception's message is shown.
->moveUsing(function (Task $task, string $to, string $from) {
if ($to === 'done' && $task->openChecks()->exists()) {
throw new \RuntimeException('Close the open checks first.');
}
$task->update(['status' => $to, 'completed_at' => $to === 'done' ? now() : null]);
})
Throw Packstub\Kanban\Exceptions\MoveRejected to refuse with a message you want shown as-is; any other exception's message is shown too, or "The move did not go through." when it has none.
Reordering
->reorderable('sort') lets users order cards inside a column (and choose the position when moving to another one). The attribute is an integer column; after each drop the positions of the target column's loaded cards are stored as 1, 2, 3… Ids from other columns, or outside the query, are ignored.
->reorderable('sort')
->sortBy('created_at') // the order among cards with the same position
Events
After a card changes column (not after reordering inside one), the board dispatches a Laravel event:
use Packstub\Kanban\Events\CardMoved;
Event::listen(function (CardMoved $event) {
activity()->performedOn($event->record)->log("Moved from {$event->from} to {$event->to}");
});
$event->board is the board's key() (the page class by default), handy when several boards share a model.
On the page itself, override kanbanMoved() to react in the component:
protected function kanbanMoved(string $id, string $to, array $card): void
{
Notification::make()->title('Moved')->success()->send();
}
In the browser, a kanban-card-moved event bubbles up from the board with { id, from, to, card }:
<div x-on:kanban-card-moved.window="console.log($event.detail)"></div>
Refreshing from outside
Dispatch packstub-kanban-refresh (from Livewire, $this->dispatch('packstub-kanban-refresh'), or from JavaScript on window) and the board reloads its cards with the current search and filters. Actions run from the board do it for you.