Table structure contract

Shape of the load-table response and query-table payload

This is the contract between backend and frontend. When the UI looks wrong, compare your actual JSON against this page.

Who owns this contract?

Backend owns field names and allowed values. Frontend renders them. If a column is missing, fix $TBLColumns — not the React code.

Structure response (load-table)

{
  "success": true,
  "tableName": "users",
  "columns": [],
  "filters": [],
  "advancedFilters": [],
  "rowActions": {},
  "bulkActions": [],
  "sortables": ["id", "name"],
  "defSortCol": "id",
  "defSortDir": "desc"
}

Top-level fields

FieldRequiredJunior explanationExample
tableNameYesID used in all other endpoints"users"
columnsYesTable headers and cell typesSee below
filtersNoFilter form fields[] if none
advancedFiltersNoExtra filter panelOften same as filters
rowActionsNoRow button definitionsIncludes show_details
bulkActionsNoToolbar actionsIncludes export_excel
sortablesNoColumns user may sort["id", "name"]
defSortColNoDefault sort column"id"
defSortDirNoDefault direction"desc"

Column object (columns[])

{
  "label": "Name",
  "data_src": "name",
  "type": "text",
  "sortable": true,
  "showable": true,
  "showInMobileApp": true,
  "minWidth": 120
}
FieldPurpose
labelHeader text (translated)
data_srcKey in each row object
typeRenderer — Column types
sortableShow sort UI when true
showablefalse = hidden
values_formatingBadges, boolean labels (type-specific)

Link columns add: linkStyle, linkText, linkColor, showCopyBtn.

Action columns require per-row row.actions in query items.


Filter object (filters[])

{
  "type": "text",
  "filter_name": "name",
  "label": "Name",
  "loadIf": true,
  "props": {
    "operators": ["=", "like"]
  }
}
FieldMaps to query payload
filter_namefilters[].field
props.operatorsAllowed filters[].operator values
props.select_optionsDropdown choices (select filters)

Row actions (rowActions)

Two shapes the frontend accepts:

  1. Flat{ "archive": { ...action def } }
  2. Nested{ "general_actions": { "archive": { ... } } }

Each action definition includes:

FieldPurpose
action_keyIdentifier
action_typenormal, modalOpen, toggle, etc.
action.apiFull URL to POST
methodUsually post
buttonLabel, classes, icons
need_confirmationConfirm dialog
onSuccessPost-action refresh behavior
applicableAsBulkActionAllow multi-select

Bulk actions (bulkActions[])

{
  "action_key": "export_excel",
  "label": "Export Excel",
  "method": "post",
  "action": { "api": "..." },
  "need_confirmation": false,
  "responseType": "instant"
}

Query response (query-table)

{
  "success": true,
  "items": [
    {
      "id": 1,
      "name": "Jane",
      "email": "jane@example.com",
      "row": { "actions": { "archive": { "applicable": true } } }
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 25,
    "total": 42,
    "last_page": 2
  },
  "bindings": {}
}
FieldPurpose
itemsCurrent page rows
paginationStandard Laravel-style meta
bindingsDynamic filter options

Validation workflow (backend + frontend)

  1. Backend dev: curl load-table → save JSON
  2. Frontend dev: compare Redux tableStructure with saved JSON
  3. Fix mismatches on the backend first

On this page