Paginated ListView

The Paginated ListView is a specialized list widget designed for handling large datasets by loading data in pages or chunks. Instead of loading all items at once, it fetches data incrementally as the user scrolls, providing a smooth infinite scroll experience.
This widget is essential for building feeds, search results, product listings, and any interface where the total dataset could be very large or infinite.
Use Cases
Paginated ListView is ideal for:
Social Media Feeds: Load posts, comments, or notifications incrementally as users scroll.
E-commerce Product Listings: Display thousands of products without loading everything upfront.
Search Results: Show search results page by page, improving initial load time.
News Articles: Load articles in batches for better performance.
User Directories: Display large lists of users, contacts, or team members.
Transaction History: Show financial transactions or order history with pagination.
Image Galleries: Load images progressively to reduce initial bandwidth usage.
Performance Benefit: By loading data in pages, you reduce initial load time, bandwidth usage, and memory consumption—especially critical for mobile apps with limited resources.
How to Set Up a Paginated ListView
Setting up a Paginated ListView involves three main steps:
Step 1: Create a Paginated API Call
Navigate to the API section in your project.
Create a new API call that supports pagination.
Configure the API endpoint with pagination parameters (see Pagination Variables section below).
Test the API to ensure it returns paginated data correctly.
Step 2: Add the Paginated ListView Widget
Drag the Paginated ListView widget onto your canvas.
In the properties panel, select your paginated API in the API Data Source field.
Configure the pagination type and variables (explained below).
Step 3: Design the Item Template
Add a child widget to serve as the template for each list item.
Use
${currentItem}to access data for each item.Design your item layout (e.g., a container with text, images, buttons).
Step 4: Configure Loading Indicators
Add a
firstPageLoadingIndicatorwidget (e.g., a circular progress indicator).Add a
newPageLoadingIndicatorwidget (e.g., a smaller loading spinner).These will be shown while data is being fetched.

Pagination Variables
Pagination variables control how the Paginated ListView communicates with your API to fetch successive pages of data. There are three types of pagination supported:
1. Page-Based Pagination
In page-based pagination, you request data using a page number.
How it works:
The API accepts a
pageparameter (e.g.,page=1,page=2,page=3).Each request returns a specific page of results.
The response typically includes the current page number and total pages.
API Example:
GET /api/products?page=1&limit=20
GET /api/products?page=2&limit=20Configuration:
First Page Key
Expression that returns the starting page number. Typically 1.
Next Page Key
Expression to extract the next page number from the API response. Example: ${response.body.nextPage} or ${sum(response.body.currentPage, 1)}.
Transform Items
Expression to extract the array of items from the response. Example: ${response.body.data} or ${response.body.products}.
Example Response Structure:
{
"currentPage": 1,
"totalPages": 10,
"nextPage": 2,
"data": [
{"id": 1, "name": "Product 1"},
{"id": 2, "name": "Product 2"}
]
}When to use: When your backend API uses page numbers and returns structured pagination metadata.
2. Offset-Based Pagination
In offset-based pagination, you request data using an offset value (how many items to skip) and a limit (how many items to return).
How it works:
The API accepts
offsetandlimitparameters.offsettells the API how many records to skip.limitspecifies how many records to return in this batch.You calculate the next offset by adding the limit to the current offset.
API Example:
GET /api/users?offset=0&limit=20 // First page: items 1-20
GET /api/users?offset=20&limit=20 // Second page: items 21-40
GET /api/users?offset=40&limit=20 // Third page: items 41-60Configuration:
First Page Key
The starting offset value. Typically 0.
Next Page Key
Expression to calculate the next offset. Example: ${sum(response.body.offset, response.body.limit)} or ${sum(currentOffset, 20)}.
Transform Items
Expression to extract the items array. Example: ${response.body.results}.
Example Response Structure:
{
"offset": 0,
"limit": 20,
"total": 150,
"results": [
{"id": 1, "username": "user1"},
{"id": 2, "username": "user2"}
]
}When to use: Common with REST APIs and databases that support SQL-style LIMIT/OFFSET queries. Ideal for predictable datasets where you can calculate exact positions.
3. Cursor-Based Pagination
In cursor-based pagination, you request data using a cursor token that points to the next set of results.
How it works:
The API returns a cursor (or token) pointing to the next page.
You pass this cursor in the next request to get the following batch.
Cursors are typically opaque strings or tokens.
More efficient than offset-based for large, frequently changing datasets.
API Example:
GET /api/posts?cursor=initial
GET /api/posts?cursor=eyJpZCI6MTAwfQ==
GET /api/posts?cursor=eyJpZCI6MjAwfQ==Configuration:
First Page Key
The initial cursor value. Can be null, "", or "initial" depending on your API.
Next Page Key
Expression to extract the next cursor from the response. Example: ${response.body.nextCursor} or ${response.body.pagination.next}.
Transform Items
Expression to extract the items array. Example: ${response.body.items}.
Example Response Structure:
{
"nextCursor": "eyJpZCI6MTAwfQ==",
"hasMore": true,
"items": [
{"id": 50, "title": "Post Title 1"},
{"id": 51, "title": "Post Title 2"}
]
}When to use:
Large datasets where items are frequently added/deleted (social feeds, real-time data).
When you need consistent results even if data changes between requests.
APIs that use cursor/token-based pagination (Facebook, Twitter, Stripe, etc.).
Important: The API must return null, undefined, or an empty cursor when there are no more pages. This tells the Paginated ListView to stop loading new pages.
Properties
Data Source Configuration
API Data Source
(Required) The paginated API call to use for fetching data. This API should support pagination parameters.
Data Source
Optional static data or expression for testing. When using an API, this is typically not needed.
Transform Items
(Required) An expression that extracts the array of items from the API response. Example: ${response.body.data}, ${response.body.results}, or ${response.body.items}.
Pagination Control
First Page Key
(Required) The initial value for the pagination parameter. For page-based: 1. For offset-based: 0. For cursor-based: null or initial token.
Next Page Key
(Required) Expression to extract or calculate the key for the next page from the API response. This determines what value gets sent in the next API request.
Scrolling Behavior
Allow Scroll
If true, the list will be scrollable. Default is true.
Scroll Direction
The direction in which the list scrolls. Can be Vertical (default) or Horizontal.
Reverse
If true, reverses the order in which items are displayed. For vertical lists, the first item appears at the bottom instead of the top. For horizontal lists, the first item appears on the right instead of the left. The scroll direction remains the same.
Initial Scroll Position
The initial scroll position when the list loads. Can be Start (default) or End.
Shrink Wrap
If true, the list sizes itself to fit its children. Use with caution as it can impact performance.
Loading Indicators
Show First Page Progress Indicator
If true, displays the firstPageLoadingIndicator widget while the initial page is loading.
Show New Page Progress Indicator
If true, displays the newPageLoadingIndicator widget while loading subsequent pages.
Children Slots
The Paginated ListView widget has three child slots that you must configure:
1. children (Item Template)
children (Item Template)Purpose: The widget template used to render each item in the list.
Configuration:
Add a single child widget (e.g., Container, Card, or custom component).
This widget will be repeated for each item in the data.
Use
${currentItem}to access the data for each item.Use
${currentIndex}to access the item's position in the list.
Example: A Container with:
Text widget displaying
${currentItem.title}Image widget showing
${currentItem.imageUrl}Button with onClick action
2. firstPageLoadingIndicator
firstPageLoadingIndicatorPurpose: Widget displayed while the first page of data is being loaded (initial load).
Configuration:
Typically a centered circular progress indicator.
Can include loading text, skeleton screens, or placeholder content.
Shown only on the very first load when no data is available yet.
Example Widgets:
Circular Progress Indicator
Linear Progress Bar
Skeleton loader (multiple placeholder containers)
Custom loading animation
3. newPageLoadingIndicator
newPageLoadingIndicatorPurpose: Widget displayed at the bottom of the list while loading additional pages.
Configuration:
Usually a smaller progress indicator.
Appears at the end of the list when the user scrolls near the bottom.
Should be subtle so it doesn't disrupt the user's scrolling experience.
Example Widgets:
Small Circular Progress Indicator
Horizontal loading bar
Text: "Loading more..."
Custom pagination loader

Complete Setup Example
Here's a comprehensive example of setting up a Paginated ListView for a product catalog using page-based pagination:
1. API Configuration
Endpoint: https://api.example.com/products Method: GET Query Parameters:
page: Variable -${pageNumber}(integer)limit: Fixed value -20
2. Paginated ListView Properties
API Data Source:
getProducts(your API call)First Page Key:
1Next Page Key:
${response.body.pagination.nextPage}Transform Items:
${response.body.data}Show First Page Progress Indicator:
trueShow New Page Progress Indicator:
true
3. Children Configuration
Item Template (children):
Container with padding
Row
Image:
${currentItem.imageUrl}Column
Text:
${currentItem.name}Text:
$${currentItem.price}
First Page Indicator (firstPageLoadingIndicator):
Column (centered)
Circular Progress Indicator
Text: "Loading products..."
New Page Indicator (newPageLoadingIndicator):
Container (centered, small padding)
Circular Progress Indicator (smaller size)
Accessing Item Data
Inside the children template, you have access to special variables:
currentItem
The data object for the current list item.
${currentItem.name}, ${currentItem.id}
currentIndex
The zero-based index of the current item in the list.
${currentIndex} returns 0, 1, 2...
For object arrays:
${currentItem.title}
${currentItem.user.name}
${currentItem.price}For simple arrays:
${currentItem} // The value itselfHandling End of Data
The Paginated ListView needs to know when there are no more pages to load. This is determined by the Next Page Key expression:
When to stop loading:
When
Next Page KeyreturnsnullWhen
Next Page KeyreturnsundefinedWhen
Next Page Keyis empty or invalid
Examples:
Page-based with hasMore flag:
${if(response.body.hasMore, response.body.nextPage, null)}Offset-based with total count:
${if(lt(sum(response.body.offset, response.body.limit), response.body.total), sum(response.body.offset, 20), null)}Cursor-based:
${response.body.nextCursor} // API returns null when no more dataError Handling
When the API call fails (network error, timeout, or API error):
The loading indicator disappears.
The user can pull to refresh to retry.
Already loaded items remain visible.
Consider adding error state widgets for better UX.
Best Practice: Add error handling in your API call configuration and show appropriate error messages to users.
Best Practices
Choose the right page size: Balance between fewer requests (larger pages) and faster initial load (smaller pages). 20-50 items per page is common.
Show loading states clearly: Users should always know when data is being fetched.
Handle errors gracefully: Network issues are common on mobile. Provide retry mechanisms.
Test with slow networks: Ensure loading indicators work properly even with slow connections.
Optimize item templates: Keep item widgets lightweight for smooth scrolling performance.
Use cursor-based pagination for real-time feeds where data changes frequently.
Implement pull-to-refresh: Allow users to manually refresh the list (use Refresh Indicator widget).
Consider caching: For offline support, cache paginated data locally.
Guides
For comprehensive examples and real-world implementations, see:
Paginated ListView Infinite ScrollThis guide includes:
Social Media Feed - Build infinite scroll feeds with cursor-based pagination
E-Commerce Product Catalog - Create product listings with offset-based pagination
Search Results - Implement search with page-based pagination
Performance optimization tips and best practices
Default Properties
The Paginated ListView widget supports the Layout and Appearance sections from Default Properties. This includes:
PaddingandMarginBackground ColorBorderandBorder RadiusVisibility
The widget does not support the Interactions section (onClick) directly. To make items tappable, add interaction handlers to the child template widgets.
Summary
Paginated ListView is the essential widget for efficiently displaying large datasets through pagination. By loading data incrementally, it ensures fast initial load times and smooth infinite scroll experiences.
Data Loading
Incremental/on-demand
Pagination Types
Page-based, Offset-based, Cursor-based
Performance
Lazy rendering + paginated data fetching
Best For
Large datasets, infinite scroll, API-driven content
Loading States
First page indicator + new page indicator
Required Configuration
API Data Source, Transform Items, First/Next Page Keys
Key Advantage
Reduces initial load time and memory usage for large lists
Last updated