Skip to content

Row detail

Override rowDetail() to make a row expandable. Each expandable row gets a chevron that folds a detail panel open beneath it. The detail is a Fragment loaded over AJAX when the row opens — nothing is fetched for collapsed rows — so the detail can be as rich as you like without weighing down the table payload.

use Lattice\Fragments\Components\Fragment;
public function rowDetail(array $row): ?Fragment
{
return Fragment::lazy(OrderLinesFragment::class, ['orderId' => $row['id']]);
}

Return null for rows that should not expand — those rows simply show no chevron.

The detail lives in its own #[AsFragment] class, authored and tested independently of the table. It reads the row context you passed to Fragment::lazy():

use Lattice\Core\Attributes\AsFragment;
use Lattice\Core\PageSchema;
use Lattice\Fragments\FragmentDefinition;
#[AsFragment('order-lines')]
final class OrderLinesFragment extends FragmentDefinition
{
public function schema(PageSchema $schema): PageSchema
{
$order = Order::with('lines')->findOrFail($this->context('orderId'));
return $schema->component(/* … the order's lines … */);
}
}

Because it is a real fragment, the detail inherits the whole Fragment pipeline: a signed per-row endpoint, authorization, the loading skeleton, and per-fragment reload events.

  • The chevron toggles the row; the rest of the row stays free for row actions and row clicks.
  • Several rows can be open at once.
  • Expansion is client-side and resets when the table reloads, re-sorts, re-filters, or paginates; the detail re-fetches each time a row opens.

Override rowClick() to make the whole row clickable. A RowClick carries exactly one behavior — the same four a button or link can carry:

use Lattice\Table\Components\RowClick;
public function rowClick(array $row): ?RowClick
{
return RowClick::make()->href(route('products.edit', $row['id']));
}
Behavior What a click does
->href($url) Visits the URL. Cmd/ctrl-click and middle-click open it in a new tab.
->action(ArchiveProduct::class, ['product_id' => $row['id']]) Runs the action — including its confirmation, its action form, and the effects it returns.
->modal(fn () => Modal::make(...)) Opens the modal.
->effects(Effects::toast('Saved')) Dispatches the effects client-side.

Return null for rows that should not react to a click. A row whose action the current user may not run stays unclickable, so a row click never offers what an action button would hide.

public function rowClick(array $row): ?RowClick
{
return RowClick::make()->modal(fn (): Modal => Modal::make('product')
->title($row['name'])
->schema([Form::use(EditProductForm::class)]));
}

A clickable row gets a hover highlight, a pointer cursor, and keyboard focus — Enter and Space activate it. Clicks on an interactive element inside the row — a checkbox, the expand chevron, an action button or link — are left alone, and a row whose action is still running ignores further clicks.