Can flutter PaginatedDataTable rowsPerPage be set to a number not divisible by 10?
UPDATE
Data used by the FutureBuilder is fetched from a local server. At first, the list contains 3 items which results into empty DataRows being created.
My Problem
What I've Tried
SAMPLE CODE
import 'package:flutter/material.dart';
import 'package:nvip/constants.dart';
import 'package:nvip/data_repo/network/centers_repo.dart';
import 'package:nvip/data_repo/tables/data_source_centers.dart';
import 'package:nvip/models/vaccination_center.dart';
class VaccinationCentersTableScreen extends StatelessWidget {
@override
Widget build(BuildContext context) => _CentersScreenBody();
}
class _CentersScreenBody extends StatefulWidget {
@override
__CentersScreenBodyState createState() => __CentersScreenBodyState();
}
class __CentersScreenBodyState extends State<_CentersScreenBody> {
int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage; // This one works
int _columnIndex = 1;
bool _isSortAscending = true;
Future<List<VaccineCenter>> _centers;
CentersTableDataSource _tableDataSource;
var _scaffoldKey = GlobalKey<ScaffoldState>();
void _sort<T>(Comparable<T> getField(VaccineCenter c), int columnIndex,
bool isSortAscending) {
_tableDataSource?.sort(getField, isSortAscending);
setState(() {
_columnIndex = columnIndex;
_isSortAscending = isSortAscending;
});
}
@override
void initState() {
super.initState();
_centers = VaccineCentersDataRepo().getCenters();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
Navigator.pushReplacementNamed(context, Routes.keyHome);
},
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("Vaccination Centers"),
centerTitle: true,
leading: IconButton(
icon: Icon(Constants.backIcon),
onPressed: () {
Navigator.pushReplacementNamed(context, Routes.keyHome);
},
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
tooltip: "Add vaccination center",
onPressed: () {
Navigator.pushReplacementNamed(context, Routes.keyPovAdd);
},
)
],
),
body: FutureBuilder<List<VaccineCenter>>(
future: _centers,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Constants.showHasNoDataWidget(
context,
"No vaccination center(s) / place(s) of vaccinations found. "
"Press the (+) sign to add a new record.",
);
} else {
if (snapshot.hasData) {
var centerList = snapshot.data;
var centersCount = centerList.length;
var defaultRowsPerPage = PaginatedDataTable.defaultRowsPerPage;
_rowsPerPage = centersCount < defaultRowsPerPage
? centersCount
: defaultRowsPerPage;
_tableDataSource = CentersTableDataSource(centerList);
return SingleChildScrollView(
child: PaginatedDataTable(
header: Text("Places of Vaccination"),
rowsPerPage: _rowsPerPage,
onRowsPerPageChanged: (rowCount) {
setState(() {
_rowsPerPage = rowCount;
});
},
sortColumnIndex: _columnIndex,
sortAscending: _isSortAscending,
onSelectAll: (isAllChecked) =>
_tableDataSource?.selectAll(isAllChecked),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
tooltip: "Add vaccination center",
onPressed: () {
Navigator.pushReplacementNamed(
context, Routes.keyPovAdd);
},
),
IconButton(
icon: Icon(Icons.delete_forever),
tooltip: "Delete vaccination center(s).",
onPressed: () {
Constants.showSnackBar(
_scaffoldKey, "Delete button clicked");
},
)
],
columns: <DataColumn>[
DataColumn(
label: Text("No."),
numeric: true,
onSort: (ci, isSortAscending) => _sort<num>(
(c) => centerList.indexOf(c), ci, isSortAscending),
),
DataColumn(
label: Text("Name"),
onSort: (ci, isSortAscending) =>
_sort<String>((c) => c.name, ci, isSortAscending),
),
],
source: _tableDataSource,
),
);
}
}
return Center(child: CircularProgressIndicator());
},
),
),
);
}
}
ERROR LOG
I/flutter ( 8474): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 8474): The following assertion was thrown building FutureBuilder<List<VaccineCenter>>(dirty, state:
I/flutter ( 8474): _FutureBuilderState<List<VaccineCenter>>#92379):
I/flutter ( 8474): 'package:flutter/src/material/paginated_data_table.dart': Failed assertion: line 87 pos 19:
I/flutter ( 8474): 'availableRowsPerPage != null && availableRowsPerPage.contains(rowsPerPage)': is not true.
I/flutter ( 8474):
I/flutter ( 8474): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter ( 8474): more information in this error message to help you determine and fix the underlying cause.
I/flutter ( 8474): In either case, please report this assertion by filing a bug on GitHub:
I/flutter ( 8474): https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter ( 8474):
I/flutter ( 8474): When the exception was thrown, this was the stack:
I/flutter ( 8474): #2 new PaginatedDataTable.<anonymous closure> (package:flutter/src/material/paginated_data_table.dart:87:19)
I/flutter ( 8474): #3 new PaginatedDataTable (package:flutter/src/material/paginated_data_table.dart:89:9)
I/flutter ( 8474): #4 __CentersScreenBodyState.build.<anonymous closure> (package:nvip/scenes/vaccination_centers/screen_center_table.dart:86:26)
I/flutter ( 8474): #5 _FutureBuilderState.build (package:flutter/src/widgets/async.dart)
I/flutter ( 8474): #6 StatefulElement.build (package:flutter/src/widgets/framework.dart:3809:27)
I/flutter ( 8474): #7 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3721:15)
I/flutter ( 8474): #8 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
I/flutter ( 8474): #9 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2286:33)
I/flutter ( 8474): #10 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:676:20)
I/flutter ( 8474): #11 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5)
I/flutter ( 8474): #12 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
I/flutter ( 8474): #13 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
I/flutter ( 8474): #14 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
I/flutter ( 8474): #15 _invoke (dart:ui/hooks.dart:154:13)
I/flutter ( 8474): #16 _drawFrame (dart:ui/hooks.dart:143:3)
I/flutter ( 8474): (elided 2 frames from class _AssertionError)
I/flutter ( 8474): ════════════════════════════════════════════════════════════════════════════════════════════════════
UPDATE 2
My DataTableSource
import 'package:flutter/material.dart';
import 'package:nvip/models/vaccination_center.dart';
class CentersTableDataSource extends DataTableSource {
final List<VaccineCenter> _centers;
int _rowsSelectedCount = 0;
CentersTableDataSource(this._centers);
@override
DataRow getRow(int index) {
assert(index >= 0);
if (index >= _centers.length) return null;
final VaccineCenter center = _centers[index];
return DataRow.byIndex(
index: index,
selected: center.isSelected,
onSelectChanged: (selected) {
if (center.isSelected != selected) {
_rowsSelectedCount += selected ? 1 : -1;
center.isSelected = selected;
notifyListeners();
}
},
cells: <DataCell>[
DataCell(Text("${index + 1}")),
DataCell(Text(center.name)),
],
);
}
@override
bool get isRowCountApproximate => false;
@override
int get rowCount => _centers.length;
@override
int get selectedRowCount => _rowsSelectedCount;
void sort<T extends Object>(
Comparable<T> getField(VaccineCenter d), bool isAscending) {
_centers.sort((a, b) {
if (isAscending) {
final VaccineCenter c = a;
a = b;
b = c;
}
final Comparable<T> aValue = getField(a);
final Comparable<T> bValue = getField(b);
return Comparable.compare(aValue, bValue);
});
notifyListeners();
}
void selectAll(bool isAllChecked) {
_centers.forEach((center) => center.isSelected = isAllChecked);
_rowsSelectedCount = isAllChecked ? _centers.length : 0;
notifyListeners();
}
}
import 'package:flutter/material.dart';
class DemoTable extends StatelessWidget {
@override
Widget build(BuildContext context) {
return _DemoTableBody();
}
}
class _DemoTableBody extends StatefulWidget {
@override
__DemoTableBodyState createState() => __DemoTableBodyState();
}
class __DemoTableBodyState extends State<_DemoTableBody> {
int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;
// A Variable to hold the length of table based on the condition of comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage
int _rowsPerPage1 = PaginatedDataTable.defaultRowsPerPage;
@override
Widget build(BuildContext context) {
//Obtain the data to be displayed from the Derived DataTableSource
var dts = DTS();
// dts.rowcount provides the actual data length, ForInstance, If we have 7 data stored in the DataTableSource Object, then we will get 12 as dts.rowCount
var tableItemsCount = dts.rowCount;
// PaginatedDataTable.defaultRowsPerPage provides value as 10
var defaultRowsPerPage = PaginatedDataTable.defaultRowsPerPage;
// We are checking whether tablesItemCount is less than the defaultRowsPerPage which means we are actually checking the length of the data in DataTableSource with default PaginatedDataTable.defaultRowsPerPage i.e, 10
var isRowCountLessDefaultRowsPerPage = tableItemsCount < defaultRowsPerPage;
// Assigning rowsPerPage as 10 or acutal length of our data in stored in the DataTableSource Object
_rowsPerPage =
isRowCountLessDefaultRowsPerPage ? tableItemsCount : defaultRowsPerPage;
return Scaffold(
appBar: AppBar(
title: Text("Demo Paginated Table"),
),
body: SingleChildScrollView(
child: PaginatedDataTable(
header: Text('data with 7 rows per page'),
// comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage and then assigning it to _rowPerPage1 variable which then set using the setsState()
onRowsPerPageChanged: isRowCountLessDefaultRowsPerPage // The source of problem!
? null
: (rowCount) {
setState(() {
_rowsPerPage1 = rowCount;
});
},
columns: <DataColumn>[
DataColumn(label: Text('row')),
DataColumn(label: Text('name')),
],
source: dts,
//Set Value for rowsPerPage based on comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage
rowsPerPage:
isRowCountLessDefaultRowsPerPage ? _rowsPerPage : _rowsPerPage1,
),
),
);
}
}
class DTS extends DataTableSource {
@override
DataRow getRow(int index) {
return DataRow.byIndex(
index: index,
cells: [
DataCell(Text('row #$index')),
DataCell(Text('name #$index')),
],
);
}
@override
int get rowCount => 9; // Manipulate this to which ever value you wish
@override
bool get isRowCountApproximate => false;
@override
int get selectedRowCount => 0;
}
This error is caused by the values provided by flutter. rowsPerPage can only be 10, 20, 50 and 100.
snapshot source PaginatedDataTable
This is specified in the source PaginatedDataTable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With