query-table

POST paginated data with filters and sorting

query-table answers: "Give me the actual rows for this page, with these filters and sort order." Call it after load-table — the frontend calls it on mount and whenever the user changes filters, sort, or page.

Request

POST /api/api-table/control-tables/query-table/{tableName}
Content-Type: application/json
Authorization: Bearer {token}

Full body example

{
  "filters": [
    { "field": "name", "operator": "like", "value": "john" },
    { "field": "status", "operator": "=", "value": "active" }
  ],
  "sorts": [
    { "field": "created_at", "direction": "desc" }
  ],
  "page": 1,
  "perPage": 25,
  "params": {
    "warehouseId": "abc"
  }
}

Field reference

FieldDefaultDescription
filters[]Array of { field, operator, value }field matches filter filter_name
sorts[]When empty, uses defSortCol / defSortDir from structure
page11-based page index
perPage20Rows per page
params{}Scoped context for table constructor / builder

Response

{
  "success": true,
  "items": [
    { "id": 1, "name": "John", "email": "john@example.com", "row": { "actions": {} } }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 25,
    "total": 100,
    "last_page": 4
  },
  "bindings": {
    "category_id": [{ "value": 1, "label": "Electronics" }]
  }
}

items row shape

Each item uses data_src keys from your column definitions. Relation fields use __ (e.g. category__name). Action columns include nested row.actions.

bindings

Populated when your table implements bindings() — dynamic select options that may change per query (e.g. dependent dropdowns).

What happens on the server

  1. APITablesService::queryData() instantiates your table
  2. prepareQueryBuilder($filters) applies each filter to $this->builder
  3. Sort clauses applied from sorts
  4. Eloquent paginates: $builder->paginate($perPage, ['*'], 'page', $page)
  5. DynamicAPITableCollection formats each row through column callbacks

Performance

Add with([...]) in setInitialBuilder() for relations used in columns. Without eager loading, each row may trigger extra queries (N+1).

Debugging empty results

CheckCommand / action
Rows exist in DB?User::count() in tinker
Builder over-filtered?Temporarily simplify setInitialBuilder()
Filter field typo?Compare field in POST with filter_name in structure
Auth user scope?Global scopes on model may hide rows

Example curl

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

On this page