Quasar v2 q-table server-side pagination: empty rows and wrong page totals
Diagnose and fix empty Quasar v2 q-table rows and incorrect page counts when using server-side pagination.
31 Aug 2025, 12:44 UTC

Problem: q-table is empty or shows the wrong number of pages when server mode is on
In Quasar v2, adding server to q-table turns off local sorting, filtering, and pagination. The component expects your backend to handle those operations and tell it how many total records exist. If your table renders no rows, or the pagination controls show one page despite many backend records, the cause is almost always a missing or incomplete @request handler.
Useful takeaway: server does not fetch data for you. It only changes where pagination logic lives. You must listen to request, call your API, assign the returned items to rows, and set rowsNumber to the total record count returned by the backend.
Recognizable conditions and likely causes
| Symptom | Likely cause | First check |
|---|---|---|
Table body is empty after adding server | No @request handler, or handler never assigns data to rows | Open browser DevTools Network tab, change pages, and confirm a request fires |
| Pagination shows one page or an incorrect total | rowsNumber is not updated to the backend's total count | Inspect rowsNumber after the API response arrives |
| Client-side filter input has no effect | Local filtering is disabled when server is true | Confirm filtering is implemented in the request handler or backend |
Ordered diagnostic checks
- Confirm the installed Quasar major version. Run this in the project root:
Required permission: read access togrep '"quasar":' package.jsonpackage.json. Expected output for this guide: a2.xvalue, such as"quasar": "^2.16.0". If the version is 3.x or missing, this q-table API may not apply; verify against the installed major version before continuing. - Verify the template wiring. Confirm
q-tablehasserverand a@requestlistener. Withoutserver, Quasar paginates locally and ignoresrowsNumberfor page calculation. - Trigger a page change and observe the network. Run
quasar dev(requires Quasar CLI available in the project or globally), open the browser, switch to the second page, and open DevTools > Network. A request should fire when the page changes. If no request fires, the@requestlistener is not attached or the component is not rendering. Risk: the dev server may fail to start if the port is already in use. - Inspect the backend response. The response should contain the page items and a separate total count. Quasar does not derive the total from the items array.
- Confirm state updates. After the response,
rowsmust contain the page items andpagination.rowsNumbermust equal the backend total.
Fixes tied to findings
Fix 1: Add the request handler and populate rows
This example uses Vue 3 Composition API syntax. Replace /api/items with your actual endpoint.
<template>
<q-table
:data="rows"
:pagination="pagination"
server
row-key="id"
:columns="columns"
@request="onRequest"
>
<template v-slot:header>...</template>
<template v-slot:body>...</template>
</q-table>
</template>
<script setup>
import { ref, reactive } from 'vue'
const columns = [
{ name: 'id', label: 'ID', field: 'id' },
{ name: 'name', label: 'Name', field: 'name', sortable: true }
]
const rows = ref([])
const pagination = reactive({
page: 1,
rowsPerPage: 10,
sortBy: 'id',
descending: false,
rowsNumber: 0
})
async function onRequest (props) {
const { page, rowsPerPage, sortBy, descending } = props.pagination
const url = `/api/items?page=${page}&limit=${rowsPerPage}&sort=${sortBy}&order=${descending ? 'desc' : 'asc'}`
try {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`Backend returned ${response.status}`)
}
const payload = await response.json()
rows.value = payload.items ?? []
pagination.rowsNumber = Number(payload.total ?? 0)
} catch (error) {
console.error('q-table server request failed', error)
rows.value = []
pagination.rowsNumber = 0
}
}
</script>
props.pagination is the pagination bound object Quasar passes to the handler. It includes page, rowsPerPage, sortBy, descending, and the current rowsNumber. Your backend decides how to interpret sortBy and descending; Quasar does not apply them locally in server mode.
Fix 2: Set rowsNumber on every response, including errors
If you update rows but forget rowsNumber, the pagination controls cannot compute the page count. Set rowsNumber in the success path and reset it to 0 in the error path so the table does not show stale page controls after a failed request.
Fix 3: Move filtering to the backend
When server is true, q-table disables local filtering. If your UI has a filter input, bind its value to pagination or a separate ref, include it in the onRequest URL, and have the backend return only matching records. The backend must also return the matching total count so rowsNumber stays correct.
Limitations
- Server mode shifts all sorting and filtering work to your backend. A slow API makes the table feel unresponsive unless you add a loading indicator.
rowsNumbermust be a number. If your backend returns the total as a string, coerce it withNumber()before assignment.- This pattern is documented for Quasar v2. Quasar v3 may change component props or events; confirm the installed major version with
package.jsonbefore adopting this code. q-tableoutput is identical across Quasar CLI build targets (SPA, PWA, SSR, Electron), but server-side network behavior still depends on the runtime environment's ability to reach the API.
Practical verification
After applying the fix, run quasar dev, open the table, and change to the last page. Confirm in DevTools > Network that the request includes the expected page and limit, and that rowsNumber equals the backend total. The pagination control should display the correct number of pages, and the table should show the returned items.
Escalation criteria
- No network request fires when changing pages: verify
serverand@requestare present onq-table, and confirm Quasar v2 is installed. - Request fires but the table remains empty: verify
rows.valueis assigned inside the handler and thatrow-keymatches a unique field in your data. - Request succeeds but page count is wrong: verify
pagination.rowsNumberis set to the backend total after every response, including error responses. - None of the above resolves the issue: inspect the Quasar version in
node_modules/quasar/package.jsonand compare theq-tablesource against the installed major version, because v2 and v3 APIs differ.
Rollback: this change edits frontend source only. Revert the template and script edits in version control; no database or backend state is modified by enabling server.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.