The Syncfusion Flutter DataGrid (data table) widget provides support to load data lazily with an interactive view when the grid reaches its maximum offset while scrolling down. In this blog, we are going to discuss how to enable the load-more feature in Flutter DataGrid and perform the lazy loading of data fetched from Firebase. Before getting into the steps, go through the overview of connecting Firebase to your Flutter application.
Note: In this blog, we use Firebase data as an example only. We are not going to provide the Firebase connectivity files here.
Dependency package
Include the Syncfusion Flutter DataGrid and Firebase package dependencies in the pubspec.yaml file of your project using the following code.
firebase_core: ^1.0.2 cloud_firestore: ^1.0.3 syncfusion_flutter_datagrid: ^19.1.54-beta.1
Create a model data class
Create an employee class to cast and store the Firebase data in your project.
Refer to the following code example.
import 'package:cloud_firestore/cloud_firestore.dart'; class Employee { Employee(this.employeeID, this.employeeName, this.designation, this.salary, {this.reference}); double employeeID; String employeeName; String designation; double salary; DocumentReference? reference; factory Employee.fromSnapshot(DocumentSnapshot snapshot) { Employee newEmployee = Employee.fromJson(snapshot.data()!); newEmployee.reference = snapshot.reference; return newEmployee; } factory Employee.fromJson(Map<String, dynamic> json) => _employeeFromJson(json); Map<String, dynamic> toJson() => _employeeToJson(this); @override String toString() => 'employeeName $employeeName'; } Employee _employeeFromJson(Map<String, dynamic> data) { return Employee( data['employeeID'], data['employeeName'], data['designation'], data['salary'], ); } Map<String, dynamic> _employeeToJson(Employee instance) { return { 'employeeID' : instance.employeeID, 'employeeName': instance.employeeName, 'designation': instance.designation, 'salary': instance.salary, }; }
Create a DataGridSource class and initialize the Firebase
Please follow these steps to create a DataGridSource and initialize the Firebase:
Step 1: Create DataGridSource
First, create a DataGridSource class, which is required for the SfDataGrid. With this class, we are going to obtain the row data.
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import '../model/employee.dart'; class EmployeeDataGridSource extends DataGridSource { List<DataGridRow> dataGridRows = []; List<Employee> employees = []; @override List<DataGridRow> get rows => dataGridRows; @override DataGridRowAdapter? buildRow(DataGridRow row) { return DataGridRowAdapter( cells: row.getCells().map<Widget>((dataGridCell) { if (dataGridCell.columnName == 'employeeID' || dataGridCell.columnName == 'salary') { return Container( alignment: Alignment.centerRight, padding: EdgeInsets.symmetric(horizontal: 16.0), child: Text( (dataGridCell.columnName == 'salary') ? NumberFormat.currency(locale: 'en_US', symbol: '\
Step 2: Initialize Firebase
Then, we have to initialize Firebase in the main() method to access the Firebase services.
import 'package:firebase_core/firebase_core.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(SfDataGridLoadMoreApp()); }
Step 3: Fetch data from cloud
Now, initialize the Firebase collection inside the DataGridSource class to fetch data from the cloud.
import 'package:cloud_firestore/cloud_firestore.dart'; class EmployeeDataGridSource extends DataGridSource { EmployeeDataGridSource() { collection = FirebaseFirestore.instance.collection('employees'); } late CollectionReference collection; }
Enable the lazy-loading feature in DataGrid
Now, let’s enable the lazy-loading feature in the Flutter DataGrid:
Step 1: Import packages
First, import the Flutter DataGrid and Firebase repository packages in the main.dart file using the following code.
import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_datagrid_loadmore/repositories/employee_repository.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart';
Step 2: Implement lazy loading
We can perform lazy loading by using either of the following ways in the Flutter data table:
In this blog, we are going to lazy load data using the infinite-scrolling feature in the DataGrid:
- Use the loadMoreViewBuilder callback, which will be called when the DataGrid reaches its maximum vertical offset.
- In the loadMoreViewBuilder callback, provide the loadMoreRows callback as a parameter.
- Using the loadMoreRows callback, you can load data lazily.
Refer to the following code example.
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter_datagrid_loadmore/repositories/employee_repository.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; class SfDataGridLoadMoreApp extends StatelessWidget { final EmployeeDataGridSource employeeDataGridSource = EmployeeDataGridSource(); SfDataGridLoadMoreApp() { employeeDataGridSource.loadMoreStream(); } @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: Scaffold( appBar: AppBar( title: Text('DataGrid Lazy Loading'), ), body: SfDataGrid( source: employeeDataGridSource, columnWidthMode: ColumnWidthMode.fill, columns: [ GridTextColumn( columnName: 'employeeID', label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), child: Text( 'ID', overflow: TextOverflow.ellipsis, ), alignment: Alignment.centerRight, )), GridTextColumn( columnName: 'employeeName', label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), child: Text( 'Name', overflow: TextOverflow.ellipsis, ), alignment: Alignment.centerLeft)), GridTextColumn( columnName: 'designation', label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), child: Text( 'Role', overflow: TextOverflow.ellipsis, ), alignment: Alignment.centerLeft)), GridTextColumn( columnName: 'salary', label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), child: Text( 'Salary', overflow: TextOverflow.ellipsis, ), alignment: Alignment.centerRight)), ], loadMoreViewBuilder: loadMoreInfiniteBuilder, ), ), ); } /// Hook this builder for applying the infinite scrolling support Widget loadMoreInfiniteBuilder( BuildContext context, LoadMoreRows loadMoreRows) { Future<String> loadRows() async { await loadMoreRows(); return Future<String>.value('Completed'); } return FutureBuilder<String>( initialData: 'loading', future: loadRows(), builder: (context, snapShot) { if (snapShot.data == 'loading') { return Container( height: 60.0, width: double.infinity, decoration: BoxDecoration( color: Colors.white, border: BorderDirectional( top: BorderSide( width: 1.0, color: Color.fromRGBO(0, 0, 0, 0.26)))), alignment: Alignment.center, child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Colors.deepPurple))); } else { return SizedBox.fromSize(size: Size.zero); } }); } }
Step 3: Implement busy indicator
- Then, override the handleLoadMoreRows property in the DataGridSource class to load more data lazily. This method will be called whenever the loadMoreRows callback is called from the loadMoreViewBuilder callback.
- You can use await to show a busy indicator while fetching data from Firebase. Here, we have delayed 500 ms manually to show the busy indicator for example purposes.
Refer to the following code example.
class EmployeeDataGridSource extends DataGridSource { static const double perPage = 100; List<Employee> employees = []; void addDataGridRow(Employee data) { dataGridRows.add(DataGridRow(cells: [ DataGridCell<double>(columnName: 'employeeID', value: data.employeeID), DataGridCell<String>( columnName: 'employeeName', value: data.employeeName), DataGridCell<String>(columnName: 'designation', value: data.designation), DataGridCell<double>(columnName: 'salary', value: data.salary), ])); } Future loadMoreDataFromStream() async { final stream = collection .where('employeeID', isGreaterThan: employees.isEmpty ? 1000.0 : employees.last.employeeID, isLessThan: employees.isEmpty ? 1000.0 + perPage : employees.last.employeeID + perPage) .snapshots(); stream.listen((snapShot) async { await Future.forEach(snapShot.docs, (DocumentSnapshot element) { final Employee data = Employee.fromSnapshot(element); if (!employees .any((element) => element.employeeID == data.employeeID)) { employees.add(data); addDataGridRow(data); } }); updateDataGridDataSource(); }); } @override Future<void> handleLoadMoreRows() async { /// Perform delay to load the data to show the loading indicator if required. await Future.delayed(const Duration(milliseconds: 500), () { loadMoreDataFromStream(); }); } void updateDataGridDataSource() { notifyListeners(); } }
Resource
For more information, refer to Perform lazy loading in Flutter Data Table (SfDataGrid) demo.
Conclusion
In this blog post, we have seen the steps to lazy load data in the Syncfusion Flutter DataGrid (data table) while fetching data from Firebase. With this, you can load only the required data at once and load the remaining data on demand. This will enhance your productivity and reduce the loading time, too.
Syncfusion DataGrid is also available in our Blazor, ASP.NET (Core, MVC, WebForms), Angular, React, Vue, Xamarin, Flutter, UWP, WinForms, WPF, and WinUI platforms. Use them to build powerful applications!
For existing customers, the new version is available for download from the License and Downloads page. If you are not yet a Syncfusion customer, you can try our 30-day free trial to check out our available features. Also, try our samples from this GitHub location.
You can contact us through our support forum, Direct-Trac, or feedback portal. We are always happy to assist you!
Related blogs
- What’s New in 2021 Volume 1: Flutter
- Introducing the New Flutter Treemap Widget
- API Breaking Changes in Flutter DataGrid in 2021 Volume 1
- How to Sort Data in Syncfusion Flutter Data Tables Based on Multiple Columns
).format(dataGridCell.value).toString() :
dataGridCell.value.toInt().toString(),
overflow: TextOverflow.ellipsis,
),
);
}
return Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Text(dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis),
);
}).toList());
}
void updateDataGridDataSource() {
notifyListeners();
}
}
Step 2: Initialize Firebase
Then, we have to initialize Firebase in the main() method to access the Firebase services.
Step 3: Fetch data from cloud
Now, initialize the Firebase collection inside the DataGridSource class to fetch data from the cloud.
Enable the lazy-loading feature in DataGrid
Now, let’s enable the lazy-loading feature in the Flutter DataGrid:
Step 1: Import packages
First, import the Flutter DataGrid and Firebase repository packages in the main.dart file using the following code.
Step 2: Implement lazy loading
We can perform lazy loading by using either of the following ways in the Flutter data table:
In this blog, we are going to lazy load data using the infinite-scrolling feature in the DataGrid:
- Use the loadMoreViewBuilder callback, which will be called when the DataGrid reaches its maximum vertical offset.
- In the loadMoreViewBuilder callback, provide the loadMoreRows callback as a parameter.
- Using the loadMoreRows callback, you can load data lazily.
Refer to the following code example.
Step 3: Implement busy indicator
- Then, override the handleLoadMoreRows property in the DataGridSource class to load more data lazily. This method will be called whenever the loadMoreRows callback is called from the loadMoreViewBuilder callback.
- You can use await to show a busy indicator while fetching data from Firebase. Here, we have delayed 500 ms manually to show the busy indicator for example purposes.
Refer to the following code example.
Resource
For more information, refer to Perform lazy loading in Flutter Data Table (SfDataGrid) demo.
Conclusion
In this blog post, we have seen the steps to lazy load data in the Syncfusion Flutter DataGrid (data table) while fetching data from Firebase. With this, you can load only the required data at once and load the remaining data on demand. This will enhance your productivity and reduce the loading time, too.
Syncfusion DataGrid is also available in our Blazor, ASP.NET (Core, MVC, WebForms), Angular, React, Vue, Xamarin, Flutter, UWP, WinForms, WPF, and WinUI platforms. Use them to build powerful applications!
For existing customers, the new version is available for download from the License and Downloads page. If you are not yet a Syncfusion customer, you can try our 30-day free trial to check out our available features. Also, try our samples from this GitHub location.
You can contact us through our support forum, Direct-Trac, or feedback portal. We are always happy to assist you!