Skip to content

gikwegbu/pageable

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pageable

pub package License: MIT

A generic, flexible, and API-agnostic pagination container for Flutter and Dart.

pageable allows you to easily map any paginated API response into a strongly-typed Page<T> object. It captures standard pagination fields, handles "meta overflow" (so you never lose extra API data), and supports infinite scroll through simple data appending.

Features

  • Generic Container: Works with any data model that extends BaseData.
  • Flexible Mapping: Use PageConfig to map your API's field names (e.g., results vs data, current_page vs pageIndex) to internal properties.
  • Meta Overflow: All JSON fields not explicitly mapped to data are stored in a meta map for easy access.
  • Infinite Scroll Support: Easily merge pages using the append method.
  • Full Serialization: Built-in fromJson and toJson support.
  • Equality: Extends Equatable for efficient rebuilding in Flutter (e.g., with Bloc or Riverpod).

Installation

Add pageable to your pubspec.yaml:

dependencies:
  pageable: ^0.0.1

Usage

1. Define Your Data Model

Extend BaseData and implement a factory to parse your JSON.

import 'package:pageable/pageable.dart';

class Product extends BaseData {
  final int id;
  final String name;

  const Product({required this.id, required this.name});

  factory Product.fromJson(Map<String, dynamic> json) {
    return Product(id: json['id'], name: json['name']);
  }

  @override
  List<Object?> get props => [id, name];
}

2. Basic Pagination

If your API uses default names (pageIndex, pageSize, totalResults, numberOfPages, data):

final json = {
  'pageIndex': 1,
  'totalResults': 100,
  'data': [{'id': 1, 'name': 'Laptop'}],
};

final page = Page<Product>.fromJson(json, Product.fromJson);
print(page.totalResults); // 100

3. Custom API Field Mapping

If your API uses different keys, use PageConfig:

final json = {
  'current_page': 1,
  'results': [...],
  'total_count': 50,
};

final config = PageConfig(
  pageIndexKey: 'current_page',
  dataKey: 'results',
  totalResultsKey: 'total_count',
);

final page = Page<Product>.fromJson(json, Product.fromJson, config: config);

4. Infinite Scroll (Append)

Merge a newly fetched page into your existing data list:

final nextPage = await api.fetchPage(2);
final combinedPage = currentPage.append(nextPage);

5. Accessing Extra Meta Fields

Access any unmapped fields directly from the meta map:

final cursor = page.meta['next_cursor'];

Tip: Use Dart extensions for typed access!

extension ProductPageX on Page<Product> {
  String? get nextCursor => meta['next_cursor'] as String?;
}

API Reference

PageConfig

Property Default Description
pageIndexKey pageIndex Key for the current page index
pageSizeKey pageSize Key for items per page
totalResultsKey totalResults Key for total number of items
numberOfPagesKey numberOfPages Key for total number of pages
dataKey data Key for the list of items

Page<T>

Property Type Description
data List<T>? The list of typed items
meta Map<String, dynamic> All other API fields
pageIndex int Convenience getter for meta['pageIndex']
pageSize int Convenience getter for meta['pageSize']
totalResults int Convenience getter for meta['totalResults']
numberOfPages int Convenience getter for meta['numberOfPages']

Author

George Ikwegbu
Contact: 07377349751

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

A generic, flexible, API-agnostic pagination container for Flutter and Dart. Supports dynamic field mapping, meta overflow, infinite scroll append, and full JSON serialisation.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages