Skip to content
Zonvoir Table LogoZonvoir Table

Column Sorting & Order Queries

Zonvoir Table supports sorting directly from column headers.

Only columns explicitly marked as sortable can be used to sort the table.

Use sortable() on any column that should support sorting.

use Zonvoir\ZonvoirTable\Columns\TextColumn;
TextColumn::make('name')
->sortable();

You can make multiple columns sortable:

public function columns(): array
{
return [
TextColumn::make('name')
->sortable(),
TextColumn::make('email')
->sortable(),
DateTimeColumn::make('created_at')
->label('Created')
->sortable(),
];
}

Users can then sort the table by interacting with the corresponding column headers.

Sorting supports both ascending and descending directions.

For example, sorting by name in ascending order:

?sort=name

Descending order is represented by prefixing the column with -:

?sort=-name

The frontend adapter handles switching between sort directions when the user interacts with a sortable column.

Use $defaultSort to define how the table should be sorted when no sort has been selected by the user.

final class UsersTable extends Table
{
protected ?string $defaultSort = 'name';
}

This sorts users by name in ascending order.

Prefix the column name with - to use descending order:

final class UsersTable extends Table
{
protected ?string $defaultSort = '-created_at';
}

This is useful for tables where the newest records should appear first.

For simple columns, Zonvoir Table can apply the sort directly to the underlying query.

Sometimes the displayed column does not map directly to a sortable database column. Use sortUsing() when you need to control how the query is ordered.

TextColumn::make('company.name')
->sortable()
->sortUsing(
fn ($query, string $direction) => $query
->orderBy('companies.name', $direction)
);

The callback receives the table query and the requested sort direction.

asc
desc

This gives you full control over the query while keeping the normal sorting experience on the frontend.

sortUsing() is also useful when a displayed value is generated or mapped from other fields.

TextColumn::make('full_name')
->sortable()
->sortUsing(
fn ($query, string $direction) => $query
->orderBy('first_name', $direction)
->orderBy('last_name', $direction)
);

The table can display full_name while the database query determines how that value should actually be sorted.

mapAs() changes the value sent to the frontend, but it does not automatically change how the database query is sorted.

TextColumn::make('name')
->mapAs(fn ($value) => strtoupper($value))
->sortable();

The displayed value may be transformed, while sorting continues to use the underlying name field.

When the displayed value requires different sorting behavior, combine it with sortUsing().

TextColumn::make('company')
->mapAs(fn ($value, User $user) => $user->company->name)
->sortable()
->sortUsing(
fn ($query, string $direction) => $query
->orderBy('companies.name', $direction)
);

The active sort is stored in the query string so the current ordering survives navigation and page reloads.

?sort=name

For descending order:

?sort=-created_at

When multiple named tables are rendered on the same page, each table keeps its sorting state isolated.

?users[sort]=name&jobs[sort]=-created_at

Only declared sortable columns are accepted as sort keys, preventing arbitrary query parameters from sorting fields that your table has not exposed.