easy_table 1.6.0 easy_table: ^1.6.0 copied to clipboard
A full customized table that builds the cells on demand. Focused on Web/Desktop Applications. Bidirectional scroll bars.
Easy Table #
- Ready for a large number of data. Building cells on demand.
- Focused on Web/Desktop Applications.
- Bidirectional scroll bars.
- Sortable.
- Resizable.
- Highly customized.
- Pinned columns.
- Multiple column sort.
Usage #
- Get started
- Columns fit
- Multi sort
- Column style
- Custom cell widget
- Row callbacks
- Pinned column
- Infinite scroll
- Theme
- Scrollbar
- Cell
- Divider
- Support this project
Get started #
EasyTableModel<Person>? _model;
@override
void initState() {
super.initState();
_model = EasyTableModel<Person>(rows: [
Person('Landon', 19),
Person('Sari', 22),
Person('Julian', 37),
Person('Carey', 39),
Person('Cadu', 43),
Person('Delmar', 72)
], columns: [
EasyTableColumn(name: 'Name', stringValue: (row) => row.name),
EasyTableColumn(name: 'Age', intValue: (row) => row.age)
]);
}
@override
Widget build(BuildContext context) {
return EasyTable<Person>(_model);
}
Columns fit #
_model = EasyTableModel<Person>(rows: rows, columns: [
EasyTableColumn(name: 'Name', weight: 5, stringValue: (row) => row.name),
EasyTableColumn(name: 'Age', weight: 1, intValue: (row) => row.age)
]);
EasyTable<Person>(_model, columnsFit: true);
Multi sort #
EasyTable(_model, multiSortEnabled: true);
Column style #
_model = EasyTableModel<Person>(rows: rows, columns: [
EasyTableColumn(name: 'Name', width: 120, stringValue: (row) => row.name),
EasyTableColumn(
name: 'Age',
width: 120,
intValue: (row) => row.age,
headerTextStyle: TextStyle(color: Colors.blue[900]!),
headerAlignment: Alignment.center,
cellAlignment: Alignment.center,
cellTextStyle: TextStyle(color: Colors.blue[700]!))
]);
Custom cell widget #
_model = EasyTableModel<Person>(rows: rows, columns: [
EasyTableColumn(name: 'Name', stringValue: (row) => row.name),
EasyTableColumn(
name: 'Rate',
width: 150,
cellBuilder: (context, row, visibleRowIndex) =>
StarsWidget(stars: row.stars))
]);
Row callbacks #
@override
Widget build(BuildContext context) {
return EasyTable<Person>(_model,
onRowTap: (person) => _onRowTap(context, person),
onRowSecondaryTap: (person) => _onRowSecondaryTap(context, person),
onRowDoubleTap: (person) => _onRowDoubleTap(context, person));
}
void _onRowTap(BuildContext context, Person person) {
...
}
void _onRowSecondaryTap(BuildContext context, Person person) {
...
}
void _onRowDoubleTap(BuildContext context, Person person) {
...
}
Pinned column #
_model = EasyTableModel(rows: persons, columns: [
EasyTableColumn(
pinned: true,
width: 30,
cellBuilder: (BuildContext context, Person row, int visibleRowIndex) {
return InkWell(
child: const Icon(Icons.edit, size: 16),
onTap: () => _onEdit(row));
}),
EasyTableColumn(name: 'Name', width: 120, stringValue: (row) => row.name),
EasyTableColumn(name: 'Age', width: 120, intValue: (row) => row.age)
]);
Infinite scroll #
final UniqueKey _tableKey = UniqueKey();
EasyTableModel<String>? _model;
bool _loading = false;
@override
void initState() {
super.initState();
List<String> rows = List.generate(30, (index) => 'value $index');
_model = EasyTableModel<String>(
rows: rows,
columns: [EasyTableColumn(name: 'Value', stringValue: (row) => row)]);
}
@override
Widget build(BuildContext context) {
EasyTable table = EasyTable<String>(_model,
key: _tableKey, onLastVisibleRowListener: _onLastVisibleRowListener);
List<Widget> children = [Positioned.fill(key: _tableKey, child: table)];
if (_loading) {
children.add(const Positioned(
child: LoadingWidget(), left: 0, right: 0, bottom: 0));
}
return Stack(children: children);
}
void _onLastVisibleRowListener(int lastVisibleRowIndex) {
if (!_loading && lastVisibleRowIndex == _model!.visibleRowsLength - 1) {
setState(() {
_loading = true;
});
Future.delayed(const Duration(seconds: 2), () {
setState(() {
_loading = false;
List<String> newValues = List.generate(
30, (index) => 'value ${_model!.visibleRowsLength + index}');
_model!.addRows(newValues);
});
});
}
}
Theme #
Scrollbar #
Horizontal scrollbar only when needed
EasyTableTheme(
child: EasyTable<Person>(_model),
data: const EasyTableThemeData(
scrollbar:
TableScrollbarThemeData(horizontalOnlyWhenNeeded: true)));
A warning is being displayed in the console due to a bug in Flutter: https://github.com/flutter/flutter/issues/103939. The error happens when the horizontal scrollbar is hidden after being visible. The following MR should fix the issue: https://github.com/flutter/flutter/pull/103948
Cell #
Null value color
_model = EasyTableModel<Person>(rows: [
Person('Landon', '+321 321-432-543'),
Person('Sari', '+123 456-789-012'),
Person('Julian', null),
Person('Carey', '+111 222-333-444'),
Person('Cadu', null),
Person('Delmar', '+22 222-222-222')
], columns: [
EasyTableColumn(name: 'Name', width: 120, stringValue: (row) => row.name),
EasyTableColumn(
name: 'Mobile', width: 150, stringValue: (row) => row.mobile)
]);
EasyTableTheme(
child: EasyTable<Person>(_model),
data: EasyTableThemeData(
cell:
CellThemeData(nullValueColor: ((rowIndex) => Colors.grey[300]))));
Divider #
Divider color and thickness
EasyTableTheme(
child: EasyTable<Person>(_model),
data: const EasyTableThemeData(
columnDividerThickness: 2,
columnDividerColor: Colors.blue,
row:
RowThemeData(dividerThickness: 2, dividerColor: Colors.green)));
TODO #
- Easiest way to create loading indicator for infinite scroll
- Collapsed rows
- Header grouping
- Row selection
- Cell edition?
- Column reorder
- Pinned column on right?
- Filter
- And everything else, the sky is the limit
Support this project #
Bitcoin #
bc1qhqy84y45gya58gtfkvrvass38k4mcyqnav803h
Ethereum (ERC-20) or Binance Smart Chain (BEP-20) #
0x9eB815FD4c88A53322304143A9Aa8733D3369985
Solana #
7vp45LoQXtLYFXXKx8wQGnzYmhcnKo1TmfqUgMX45Ad8