In today's fast-paced world of app development, presenting data in a structured and user-friendly manner is essential. Flutter, Google's UI toolkit for building natively compiled applications for mobile, web, and desktop from a single codebase, provides a powerful widget called PaginatedDataTable
that allows you to display large datasets in a paginated and organized way. In this blog post, we'll explore a comprehensive example of using the PaginatedDataTable
widget in Flutter, along with explanations of its various components.
What is PaginatedDataTable
?
The PaginatedDataTable
widget in Flutter combines a DataTable
with built-in pagination. It's a great choice when you have a large dataset that needs to be displayed in a tabular format while allowing users to navigate through different pages of the data. It provides a user-friendly interface for sorting and selecting data, making it a powerful tool for presenting complex information.
Prerequisites
Before we dive into the example, make sure you have Flutter installed and a basic understanding of the framework's concepts.
Example: Creating a PaginatedDataTable
Let's say we're developing a task management app, and we want to display a list of tasks in a paginated table format. Here's how we can achieve this using the PaginatedDataTable
widget.
Step 1: Import Required Libraries
import 'package:flutter/material.dart';
Step 2: Create a Data Source
First, we need to define a data source that provides the data to be displayed in the table. In this example, we'll create a simple list of tasks.
class Task { final String name; final String priority; final DateTime dueDate; Task({required this.name, required this.priority, required this.dueDate}); } class TaskDataSource extends DataTableSource { final List<Task> _tasks = [ Task(name: 'Buy groceries', priority: 'High', dueDate: DateTime.now()), // Add more tasks here... ]; @override DataRow? getRow(int index) { if (index >= _tasks.length) { return null; } final task = _tasks[index]; return DataRow.byIndex( index: index, cells: [ DataCell(Text(task.name)), DataCell(Text(task.priority)), DataCell(Text(task.dueDate.toString())), ], ); } @override bool get isRowCountApproximate => false; @override int get rowCount => _tasks.length; @override int get selectedRowCount => 0; }
In this data source, we've defined a Task
class representing a task's name, priority, and due date. The TaskDataSource
class extends DataTableSource
and provides the necessary methods for the PaginatedDataTable
to retrieve data.
Step 3: Create a PaginatedDataTable
Now that we have our data source ready, we can create the PaginatedDataTable
widget.
class PaginatedDataTableExample extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Task List'), ), body: SingleChildScrollView( child: PaginatedDataTable( header: Text('Tasks'), columns: [ DataColumn(label: Text('Task')), DataColumn(label: Text('Priority')), DataColumn(label: Text('Due Date')), ], source: TaskDataSource(), rowsPerPage: 10, ), ), ); } }
In this code snippet, we wrap the PaginatedDataTable
in a SingleChildScrollView
to ensure that the table fits on the screen even if the data exceeds the available space. We provide a header and column definitions using the DataColumn
widget. The TaskDataSource
instance is passed as the data source, and rowsPerPage
determines how many rows are displayed per page.
Step 4: Run the App
To see our PaginatedDataTable
in action, we need to integrate it into the app's main structure. Make sure to include the PaginatedDataTableExample
widget in your app's widget tree.
void main() { runApp(MaterialApp( home: PaginatedDataTableExample(), )); }
Now, when you run the app, you should see a paginated table displaying tasks with columns for task name, priority, and due date. The table will automatically handle pagination and provide a smooth user experience.
Complete Source Code
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'FlutterforGeeks', debugShowCheckedModeBanner: false, theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.green), useMaterial3: true, ), home: PaginatedDataTableExample(), ); } } class PaginatedDataTableExample extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('FlutterforGeeks'), ), body: SingleChildScrollView( child: PaginatedDataTable( header: const Text('Tasks'), columns: const [ DataColumn(label: Text('Task')), DataColumn(label: Text('Priority')), DataColumn(label: Text('Due Date')), ], source: TaskDataSource(), rowsPerPage: 10, ), ), ); } } class Task { final String name; final String priority; final DateTime dueDate; Task({required this.name, required this.priority, required this.dueDate}); } class TaskDataSource extends DataTableSource { final List<Task> _tasks = [ Task(name: 'Todo1', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo2', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo3', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo4', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo5', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo6', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo7', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo8', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo9', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo10', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo11', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo12', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo13', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo14', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo15', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo16', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo17', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo18', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo19', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo20', priority: 'High', dueDate: DateTime.now()), Task(name: 'Todo21', priority: 'High', dueDate: DateTime.now()), // Add more tasks here... ]; @override DataRow? getRow(int index) { if (index >= _tasks.length) { return null; } final task = _tasks[index]; return DataRow.byIndex( index: index, cells: [ DataCell(Text(task.name)), DataCell(Text(task.priority)), DataCell(Text(task.dueDate.toString())), ], ); } @override bool get isRowCountApproximate => false; @override int get rowCount => _tasks.length; @override int get selectedRowCount => 0; }
Video Demo
Conclusion
The PaginatedDataTable
widget in Flutter is a powerful tool for presenting and managing large datasets in a structured and user-friendly manner. By following this example and understanding its components, you can integrate paginated tables into your own Flutter applications, enhancing the way you present complex information to users. Remember to customize the example to fit your specific use case and explore additional features that the PaginatedDataTable
widget offers to create even more engaging user interfaces.