Manual Pagination - Fixed Pages
Goal
- Display a fixed number of items (e.g. 10)
- No automatic loading on scroll
- Navigation only via Next and Previous buttons, which replace the currently visible items with the next/previous page's items
Concept
Pagination is controlled using:
- A limit on the datasource
- A cursor/offset stored in context
- Buttons that modify the offset via navigation params
Layout warning
Because the list re-renders with a new set of items on every navigation, the page layout can shift (the new page may be taller or shorter than the previous one). Give the list container a fixed height (or another layout technique that reserves space) so the surrounding page does not jump when the user navigates between pages.
Required components
To implement manual pagination, configure 3 components:
- List Component
- Previous Button
- Next Button
1. List Component Configuration
Step 1 - Enable Data Source
In List Component -> Datasource:
- Enable datasource
- Choose the datasource type as needed
Step 2 - Limit (Page Size)
Set:
- Limit = 10 (or any page size you want)
This ensures only 10 elements are shown, and infinite scrolling is disabled.
Step 3 - Cursor / Offset
Add a Cursor field:
- Value: $context.offset
- Condition: $context.offset IS SET
This tells the data source from which position it should load data.
You may name the parameter something else (e.g. pageOffset), but then all references must use $context.pageOffset.
{
"content": {
"tag": "div",
"type": "html",
"content": "$context.content.name"
},
"dataSource": {
"type": "content",
"limit": 10,
"fetchOptions": {
"totalCount": true
},
"contextKey": "contents",
"cursor": {
"value": "$context.offset",
"condition": {
"value": "$context.offset",
"operation": "SET"
}
}
},
"type": "list"
}2. "Previous" Button Configuration
Visibility condition
Hide the button conditionally rather than disabling it, so it is simply not in the DOM on the first page:
$context.offset > 0Tap action
Set Tap Action -> Navigation:
- Path: current path
- Params:
- Key: offset
- Value: $functions.add($context.offset, -10)
This decreases the offset by the page size and loads the previous set of elements.
{
"tag": "div",
"type": "html",
"content": "prev page",
"tap": {
"type": "navigate",
"params": {
"offset": "$functions.add($context.offset, -10)"
}
},
"condition": {
"compareValue": "$functions.add($context.offset, 0)",
"value": "0",
"negated": true
}
}3. Next Button Configuration
Visibility condition
Hide the button conditionally when there is no further page:
$context.contents.hasNextPage == trueWhere contents is the datasource result context key, and hasNextPage indicates more data is available.
Tap action
Set Tap Action -> Navigation:
- Path: current path
- Params:
- Key: offset
- Value: $functions.add($context.offset, 10)
This increases the offset by the page size and loads the next set of elements.
{
"tag": "div",
"type": "html",
"content": "next page",
"tap": {
"type": "navigate",
"params": {
"offset": "$functions.add($context.offset, 10)"
}
},
"condition": {
"operation": "EQUALS",
"compareValue": "true",
"value": "$context.contents.hasNextPage"
}
}Custom function
Add the add function to custom.server.js:
window.$functions = {
add: (val, plus) => parseInt(val ?? '0') + plus
}Note: an earlier draft of this page also defined a toJson helper for debugging context values during setup. Remove it before publishing - it has no purpose in a finished configuration.
Summary
Feature | Infinite Scrolling | Manual Pagination - Fixed Pages |
|---|---|---|
Auto-load on scroll | Yes | No |
Uses limit | No | Yes |
Uses offset/cursor | No | Yes |
Requires buttons | No | Yes - Next / Prev |
Replaces or appends items | - | Replaces |
Page size control | Batch Size | Limit |