[英]Flutter PaginatedDataTable rowsPerPage
Can flutter PaginatedDataTable rowsPerPage be set to a number not divisible by 10?能扑PaginatedDataTable rowsPerPage被设置为一个数字不是10整除?
UPDATE更新
Data used by the FutureBuilder is fetched from a local server. FutureBuilder 使用的数据是从本地服务器获取的。 At first, the list contains 3 items which results into empty DataRows being created.
起初,该列表包含 3 个项目,这会导致创建空的 DataRow。
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更新 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.这个错误是由flutter提供的值引起的。 rowsPerPage can only be 10, 20, 50 and 100.
rowsPerPage 只能是 10、20、50 和 100。
snapshot source PaginatedDataTable快照源分页数据表
This is specified in the source PaginatedDataTable .这是在源PaginatedDataTable 中指定的。
I'm leaving this for the next guy since I just battled this recently.我要把这个留给下一个家伙,因为我最近刚和这个战斗过。
Right now, it seems like PaginatedDataTable has a couple of bugs in it... this is one of them.现在,PaginatedDataTable 似乎有几个错误……这是其中之一。 If the number of data elements doesn't exactly equal the selected number of rows per page, the PaginatedDataTable widget puts in 'filler rows'
如果数据元素的数量不完全等于每页选定的行数,PaginatedDataTable 小部件将放入“填充行”
Until this is fixed, I'd recommend taking the flutter PaginatedDataTable widget in the file paginated_data_table.dart and putting it in your project in order to customize it.在修复此问题之前,我建议在文件 paginated_data_table.dart 中使用 flutter PaginatedDataTable 小部件并将其放入您的项目中以对其进行自定义。 (you'll have to replace all of the dependencies that aren't found with a simple
import 'package:flutter/material.dart';
(您必须用简单的
import 'package:flutter/material.dart';
替换所有未找到的依赖项import 'package:flutter/material.dart';
In order to limit the number of seen rows, add the lines with // <--- below in the _getRows method seen below:为了限制看到的行数,在下面看到的 _getRows 方法中添加带有 // <--- 下面的行:
List<DataRow> _getRows(int firstRowIndex, int rowsPerPage) {
final List<DataRow> result = <DataRow>[];
final int nextPageFirstRowIndex = firstRowIndex + rowsPerPage;
bool haveProgressIndicator = false;
for (int index = firstRowIndex; index < nextPageFirstRowIndex; index += 1) {
if (index < _rowCount) { // <---
// This stops "overflow" rows from appearing on the last page.
DataRow row;
if (index < _rowCount || _rowCountApproximate) {
row = _rows.putIfAbsent(index, () => widget.source.getRow(index));
if (row == null && !haveProgressIndicator) {
row ??= _getProgressIndicatorRowFor(index);
haveProgressIndicator = true;
}
}
row ??= _getBlankRowFor(index);
result.add(row);
} // <---
}
return result;
}
Additionally, the page count will now be off, so you'll have to change this section below in order to add the ternary operator to change the final count:此外,页面计数现在将关闭,因此您必须更改下面的此部分以添加三元运算符以更改最终计数:
Text(
localizations.pageRowsInfoTitle(
_firstRowIndex + 1,
(_firstRowIndex + widget.rowsPerPage <= _rowCount)?_firstRowIndex + widget.rowsPerPage:_rowCount,
_rowCount,
_rowCountApproximate,
),
),
rowsPerPage
and availableRowsPerPage
need to be defined together. rowsPerPage
和availableRowsPerPage
需要一起定义。 For example:例如:
_rowsPerPage = 5;
recalculate _rowsPerPage
in build method:在构建方法中重新计算
_rowsPerPage
:
@override
Widget build(BuildContext context) {
_rowsPerPage = widget.items.length > 5 ? 5 : widget.items.length;
return _buildCollectivePanel();
}
then add rowsPerPage
, availableRowsPerPage
to the PaginatedDataTable
in _buildCollectivePanel()
然后添加
rowsPerPage
, availableRowsPerPage
到PaginatedDataTable
在_buildCollectivePanel()
PaginatedDataTable(
header: Text("dataTableHeader"),
rowsPerPage: _rowsPerPage,
availableRowsPerPage: <int>[_rowsPerPage, _rowsPerPage * 2, _rowsPerPage * 5, _rowsPerPage * 10],......
Let's say you have some method that fetches data from a remote server or locally and return a list of objects like this :假设您有一些方法可以从远程服务器或本地获取数据并返回如下对象列表:
List<Map<String, String>> fetchedDataObj = [
{
"name": "Rami",
"email": "dummyemail01@gmail.com"
},
{
"name": "Kara",
"email": "dummyemail02@gmail.com"
},
{
"name": "Lina",
"email": "dummyemail03@almakana.com"
}
];
in PaginatedDataTable
widget set :在
PaginatedDataTable
小部件集中:
rowsPerPage: fetchedDataObj.length,
and和
onRowsPerPageChanged: (fetchedDataObj.length < PaginatedDataTable.defaultRowsPerPage) ? null : (r) {
// setState(() {
// _rowsPerPage = r;
// });
},
),
Hope this helps.希望这可以帮助。 Thanks
谢谢
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.