Comments (27)
Pagination is a must-have feature. There are plans to add.
I think I will do it when the filtering I'm currently doing is over.
from pluto_grid.
@Minsamin
First of all, thanks for your comments.
The features you mentioned are currently available.
stateManager.setPage()
stateManager.setPageSize()
stateManager.page
stateManager.pageSize
stateManager.totalPage
stateManager.setShowLoading()
However, additional callback events are required for filtering and sorting.
I'll try to add server-side pagination to the next release.
from pluto_grid.
Is there any progression on this feature?
from pluto_grid.
I am working on paging.
Pagination happens on the client side when the existing createFooter callback returns a pagination widget.
One pagination widget is provided by default and you can customize it.
It will be completed by tomorrow or next weekend at the latest.
from pluto_grid.
Any news on that or should I just give up on this plugin.
from pluto_grid.
Hello, are you working on the pagination part? Any ETA ? I want to use this library in my project.
from pluto_grid.
I'm thinking about how to do it, but I can't because I don't have much time.
from pluto_grid.
Hope that you can do it soon because it very very necessary for big data with render. long time for waiting
from pluto_grid.
thanks for great package, hope it will be soon
from pluto_grid.
Version 2.4.0 has been released.
example demo
https://weblaze.dev/pluto_grid/build/web/#feature/row-pagination
from pluto_grid.
I found a bug where if I filter on a paged list and then release it again, the list doesn't come back.(fixed 2.4.1)
There may be bugs due to insufficient testing. (to be fixed in next release)
If you find any other bugs, please report them to me.
from pluto_grid.
Can we use this with lazy data loading?
Like, get the particular page data from api, then put data in dataTable.
For every page, it will first fetch then show in dataTable...
from pluto_grid.
@Minsamin
That feature should be added to the server-side rendering feature.
Or you have to implement it yourself.
Most APIs can be called from StateManager that is passed as an argument to the onLoaded callback function when creating a grid.
If you use this, you will be able to implement it yourself.
from pluto_grid.
I think, if PlutoPagination has buttonPress callback(first, last, next, Prev) for user, and any method to show loading while fetching data from server, that will be helpful.
reference
https://dev-owl.github.io/advanced_datatable/#/
from pluto_grid.
stateManager.totalPage is getter only which way i can use it. Could you make an example for it
from pluto_grid.
@amasahara yes it is. `stateManager.totalPage is getter.
from pluto_grid.
So if i want so data like advance datatable i will be waiting ultil next update or another way to do it
from pluto_grid.
Hi @bosskmk,
Any progress on server-side pagination?
Thanks for such a wonderful datagrid.
Regards,
Jose
from pluto_grid.
@bosskmk how can i set the page change event?
from pluto_grid.
hi, is there a way to manually define the paging process? I'm trying to figure out how to use the paginator, below is my sample backend response.
{
data: [...],
first: "/api/v1/models?page=1&limit=50",
last: "/api/v1/models?page=261&limit=50",
next: "/api/v1/models?page=4&limit=50",
previous: "/api/v1/models?page=2&limit=50",
page_no: 3,
page_size: 50,
total_page: 261,
total_rows: 13029
}
what we are trying to achieve is something like this in UI
from pluto_grid.
I think, if PlutoPagination has buttonPress callback(first, last, next, Prev) for user, and any method to show loading while fetching data from server, that will be helpful.
Any updates about this?
from pluto_grid.
Hello,
Unfortunately from what I see the async pagination is not ready yet.
It's something that is not very complex:
1- page change event (know what page we are)
2- possibility to show a spinner
3- api call
4- refresh data
5- hide spinner
from pluto_grid.
Yes, I am planning to provide a widget for asynchronous pagination.
I just haven't started doing this yet.
I'll start this up and let you know when I'm done.
thank you
from pluto_grid.
I am not yet developing the asynchronous pagination feature, but users can implement server side pagination as shown below.
(I have plans to add features in the future)
Sorting and filtering require minor modifications to the current event part.
Currently, when a user's sorting or filtering event occurs, it is processed as local data. In server-side pagination, only the user's event is generated and the data must be imported as the event information.
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:pluto_grid/pluto_grid.dart';
import '../dummy_data/development.dart';
class EmptyScreen extends StatefulWidget {
static const routeName = 'empty';
const EmptyScreen({Key? key}) : super(key: key);
@override
_EmptyScreenState createState() => _EmptyScreenState();
}
class _EmptyScreenState extends State<EmptyScreen> {
final List<PlutoColumn> columns = DummyData.textColumns(5);
final List<PlutoRow> rows = [];
final List<PlutoRow> fakeFetchedRows = [];
late PlutoGridStateManager stateManager;
final int pageSize = 30;
@override
void initState() {
super.initState();
/// 100 data generation for fake server data.
fakeFetchedRows.addAll(
DummyData.rowsByColumns(length: 100, columns: columns),
);
}
Future<_PaginationData> fetch(
_PaginationParams params,
) async {
/// Get data from server.
final start = (params.page - 1) * pageSize;
final end = min(start + pageSize, fakeFetchedRows.length);
final fetchRows = fakeFetchedRows.getRange(start, end);
await Future.delayed(const Duration(seconds: 1));
/// Change server data to Map<String, dynamic> type.
return Future.value(
_PaginationData(
totalPage: (fakeFetchedRows.length / pageSize).ceil(),
rows: fetchRows
.map(
(e) => e.cells.map<String, dynamic>(
(key, value) => MapEntry(key, value.value),
),
)
.toList(),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
padding: const EdgeInsets.all(15),
child: PlutoGrid(
columns: columns,
rows: rows,
onChanged: (PlutoGridOnChangedEvent event) {
print(event);
},
onLoaded: (PlutoGridOnLoadedEvent event) {
stateManager = event.stateManager;
},
configuration: const PlutoGridConfiguration(),
createFooter: (s) => PlutoPaginationServerSide(s, fetch: fetch),
),
),
),
);
}
}
class PlutoPaginationServerSide extends StatefulWidget {
const PlutoPaginationServerSide(
this.stateManager, {
required this.fetch,
super.key,
});
final PlutoGridStateManager stateManager;
final Future<_PaginationData> Function(
_PaginationParams params,
) fetch;
@override
State<PlutoPaginationServerSide> createState() =>
_PlutoPaginationServerSideState();
}
class _PlutoPaginationServerSideState extends State<PlutoPaginationServerSide> {
PlutoGridStateManager get stateManager => widget.stateManager;
final int initialPage = 1;
int totalPage = 0;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setPage(initialPage);
});
}
Future<void> setPage(int page) async {
stateManager.setShowLoading(true, level: PlutoGridLoadingLevel.rows);
final data = await widget.fetch(
_PaginationParams(page: page),
);
if (totalPage != data.totalPage) setState(() => totalPage = data.totalPage);
stateManager.refRows.clearFromOriginal();
stateManager.insertRows(
0,
data.rows
.map(
(e) => PlutoRow(
cells: {
for (var v in e.entries) v.key: PlutoCell(value: v.value)
},
),
)
.toList(),
);
stateManager.setShowLoading(false);
}
@override
Widget build(BuildContext context) {
return _PaginationWidget(
iconColor: stateManager.style.iconColor,
disabledIconColor: stateManager.style.disabledIconColor,
activatedColor: stateManager.style.activatedBorderColor,
iconSize: stateManager.style.iconSize,
height: stateManager.footerHeight,
initialPage: initialPage,
totalPage: totalPage,
setPage: setPage,
);
}
}
class _PaginationData {
_PaginationData({
required this.totalPage,
required this.rows,
});
final int totalPage;
final List<Map<String, dynamic>> rows;
}
class _PaginationParams {
_PaginationParams({
required this.page,
});
final int page;
}
class _PaginationWidget extends StatefulWidget {
const _PaginationWidget({
required this.iconColor,
required this.disabledIconColor,
required this.activatedColor,
required this.iconSize,
required this.height,
this.initialPage = 1,
required this.totalPage,
required this.setPage,
});
final Color iconColor;
final Color disabledIconColor;
final Color activatedColor;
final double iconSize;
final double height;
final int initialPage;
final int totalPage;
final void Function(int page) setPage;
@override
State<_PaginationWidget> createState() => _PaginationWidgetState();
}
class _PaginationWidgetState extends State<_PaginationWidget> {
@override
void initState() {
super.initState();
_page = widget.initialPage;
}
int get totalPage => widget.totalPage;
int _page = 1;
late double _maxWidth;
final _iconSplashRadius = PlutoGridSettings.rowHeight / 2;
bool get _isFirstPage => _page < 2;
bool get _isLastPage => _page > totalPage - 1;
/// maxWidth < 450 : 1
/// maxWidth >= 450 : 3
/// maxWidth >= 550 : 5
/// maxWidth >= 650 : 7
int get _itemSize {
final countItemSize = ((_maxWidth - 350) / 100).floor();
return countItemSize < 0 ? 0 : min(countItemSize, 3);
}
int get _startPage {
final itemSizeGap = _itemSize + 1;
var start = _page - itemSizeGap;
if (_page + _itemSize > totalPage) {
start -= _itemSize + _page - totalPage;
}
return start < 0 ? 0 : start;
}
int get _endPage {
final itemSizeGap = _itemSize + 1;
var end = _page + _itemSize;
if (_page - itemSizeGap < 0) {
end += itemSizeGap - _page;
}
return end > totalPage ? totalPage : end;
}
List<int> get _pageNumbers {
return List.generate(
_endPage - _startPage,
(index) => _startPage + index,
);
}
void _firstPage() {
_movePage(1);
}
void _beforePage() {
int beforePage = _page - 1 + (_itemSize * 2);
if (beforePage < 1) {
beforePage = 1;
}
_movePage(beforePage);
}
void _nextPage() {
int nextPage = _page + 1 + (_itemSize * 2);
if (nextPage > totalPage) {
nextPage = totalPage;
}
_movePage(nextPage);
}
void _lastPage() {
_movePage(totalPage);
}
void _movePage(int page) {
setState(() {
_page = page;
widget.setPage(page);
});
}
ButtonStyle _getNumberButtonStyle(bool isCurrentIndex) {
return TextButton.styleFrom(
disabledForegroundColor: Colors.transparent,
shadowColor: Colors.transparent,
padding: const EdgeInsets.fromLTRB(5, 0, 0, 10),
backgroundColor: Colors.transparent,
);
}
TextStyle _getNumberTextStyle(bool isCurrentIndex) {
return TextStyle(
fontSize: isCurrentIndex ? widget.iconSize : null,
color: isCurrentIndex ? widget.activatedColor : widget.iconColor,
);
}
Widget _makeNumberButton(int index) {
var pageFromIndex = index + 1;
var isCurrentIndex = _page == pageFromIndex;
return TextButton(
onPressed: () {
_movePage(pageFromIndex);
},
style: _getNumberButtonStyle(isCurrentIndex),
child: Text(
pageFromIndex.toString(),
style: _getNumberTextStyle(isCurrentIndex),
),
);
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (_, size) {
_maxWidth = size.maxWidth;
final Color iconColor = widget.iconColor;
final Color disabledIconColor = widget.disabledIconColor;
return Container(
width: _maxWidth,
height: widget.height,
alignment: Alignment.center,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
IconButton(
onPressed: _isFirstPage ? null : _firstPage,
icon: const Icon(Icons.first_page),
color: iconColor,
disabledColor: disabledIconColor,
splashRadius: _iconSplashRadius,
mouseCursor: _isFirstPage
? SystemMouseCursors.basic
: SystemMouseCursors.click,
),
IconButton(
onPressed: _isFirstPage ? null : _beforePage,
icon: const Icon(Icons.navigate_before),
color: iconColor,
disabledColor: disabledIconColor,
splashRadius: _iconSplashRadius,
mouseCursor: _isFirstPage
? SystemMouseCursors.basic
: SystemMouseCursors.click,
),
..._pageNumbers.map(_makeNumberButton).toList(),
IconButton(
onPressed: _isLastPage ? null : _nextPage,
icon: const Icon(Icons.navigate_next),
color: iconColor,
disabledColor: disabledIconColor,
splashRadius: _iconSplashRadius,
mouseCursor: _isLastPage
? SystemMouseCursors.basic
: SystemMouseCursors.click,
),
IconButton(
onPressed: _isLastPage ? null : _lastPage,
icon: const Icon(Icons.last_page),
color: iconColor,
disabledColor: disabledIconColor,
splashRadius: _iconSplashRadius,
mouseCursor: _isLastPage
? SystemMouseCursors.basic
: SystemMouseCursors.click,
),
],
),
),
);
},
);
}
}
from pluto_grid.
Released PlutoGrid 5.3.0
Refer to below link.
#601
from pluto_grid.
This issue is stale because it has been open for 30 days with no activity.
from pluto_grid.
This issue was closed because it has been inactive for 14 days since being marked as stale.
from pluto_grid.
Related Issues (20)
- [Bug] Unexpected null value. rightFrozenLeftOffset HOT 2
- [Bug] Back button not working when Navigating to a Page with PlutoGrid on Android HOT 6
- > Still not resolved
- [Feature] Please add Korean language.
- Row height and styling [Help] HOT 1
- Please add a onEdit() callback to enable checks and formatting during editing HOT 1
- pluto_grid_export is not compatible with Flutter 3.22.2 and Dart 3.4.3 HOT 1
- [Bug] Using arrow keys to move around the Linux grid HOT 1
- how optimize for a huge number of records HOT 1
- 分页按钮颜色是不是不可以调整[Feature] HOT 2
- [Help] open Editing Mode on spec column (All Row ) by one click ! HOT 2
- [Help] Can we create a custom widget in cells instead of standard ones like text, number, date, time, etc? HOT 2
- [Help] how can i make the rows update automatically when a provider value changes HOT 2
- Showing two lines at the end HOT 2
- [Help] How to write text to filter field of the grid? HOT 1
- How can i set fontWeight: FontWeight.bold in PlutoRow => PlutoCell ?[Help] HOT 2
- [Bug] HOT 1
- [Help] HOT 1
- [Help] header or Footer in TextField can't editing on Flutter Web HOT 1
- Onchanged function is not called correctly HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pluto_grid.