Sorting

Server-side sort configuration and query payload

Sorting in ApiTables is always server-side. The frontend sends which column and direction; your Eloquent builder applies orderBy. The client cannot sort by columns you did not expose.

Defaults (when user has not sorted yet)

On every table class:

public string $defSortCol = 'id';
public string $defSortDir = 'desc';

These appear in the load-table response. When query-table receives "sorts": [], the package uses these defaults.

Sortable columns

Only columns marked 'sortable' => true in $TBLColumns are included in the sortables array in structure JSON.

[
    'type' => 'text',
    'label' => 'email',
    'data_src' => 'email',
    'sortable' => true,  // user can click column header to sort
],

If sortable is omitted or false, the frontend should not offer sort for that column.

Query payload

{
  "sorts": [
    { "field": "created_at", "direction": "desc" },
    { "field": "name", "direction": "asc" }
  ]
}
FieldValues
fieldMust be in sortables — usually matches data_src
directionasc or desc

Multiple sorts are applied in order (secondary sort).

Relation columns

For 'data_src' => 'category.name', sort field in payload is typically category__name (double underscore), matching query result keys.

Ensure the join exists when sorting relation columns:

$this->builder = Product::query()
    ->leftJoin('categories', 'products.category_id', '=', 'categories.id')
    ->select('products.*');

Senior: custom sort logic

Override sort application in your table class if you need computed sorts or case-insensitive ordering. The default behavior in TableAbstract maps field directly to orderBy on the builder.

Testing

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"page":1,"perPage":5,"sorts":[{"field":"name","direction":"asc"}],"filters":[]}' \
  https://app.test/api/api-table/control-tables/query-table/users

Verify first item has lowest name alphabetically.

On this page