flutterx_table 2.0.0
flutterx_table: ^2.0.0 copied to clipboard
Highly customizable Flutter table with selection, sorting, filtering, actions, column swap, paging and scrolling modules.
example/lib/main.dart
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutterx_live_data/flutterx_live_data.dart';
import 'package:flutterx_table/flutterx_table.dart';
void main() => runApp(const ExampleApp());
/// A paged table with sorting, filtering, selection, row actions and draggable columns.
class ExampleApp extends StatelessWidget {
/// Creates the example app.
const ExampleApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
title: 'flutterx_table example',
theme: ThemeData(colorSchemeSeed: Colors.blueGrey),
home: const _TablePage(),
);
}
class _TablePage extends StatefulWidget {
const _TablePage();
@override
State<_TablePage> createState() => _TablePageState();
}
class _TablePageState extends State<_TablePage> {
static final List<int> _allItems = List.generate(189, (index) => index + 1);
final MutableLiveData<PageInfo> _pageInfo = MutableLiveData(value: const PageInfo.empty(pageSize: 10));
final MutableLiveData<FilterOptions?> _filterOptions = MutableLiveData();
final MutableLiveData<SortOptions?> _sortOptions = MutableLiveData();
final LiveSet<String> _selection = LiveSet();
final LiveList<TableColumn> _columns = LiveList(
source: [
for (final id in ['A', 'B', 'C']) TableColumn(id: id, label: 'Column $id', sortable: true, filterable: true),
],
);
Future<PagedList<int>> _loadItems(PageInfo page, FilterOptions? filter, SortOptions? sort) async {
await Future<void>.delayed(const Duration(milliseconds: 200));
final query = filter?.query ?? '';
final items = [
for (final item in _allItems)
if ('${filter?.columnId ?? ''}$item'.toLowerCase().contains(query.toLowerCase())) item,
]..sort((sort?.order ?? SortOrder.asc).comparator);
final lastPage = PageInfo.computePageCount(items.length, page.pageSize) - 1;
final info = PageInfo.of(page: min(page.page, lastPage), pageSize: page.pageSize, itemsCount: items.length);
return PagedList(pageInfo: info, items: items.sublist(info.startIndex, info.endIndex));
}
void _moveColumn(TableColumn column, int oldIndex, int newIndex) => _columns.apply((columns) {
// `newIndex` is the insertion index before the column is removed, as in `ReorderableList.onReorder`.
columns.insert(newIndex > oldIndex ? newIndex - 1 : newIndex, columns.removeAt(oldIndex));
return true;
});
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text('flutterx_table')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Card(
clipBehavior: Clip.antiAlias,
child: ContentTableBuilder<int>(
pageInfo: _pageInfo,
filterOptions: _filterOptions,
sortOptions: _sortOptions,
itemsBuilder: _loadItems,
crossAxisAlignment: CrossAxisAlignment.stretch,
builder: (context, items, loading) => Flexible(
child: AutoScrollView(
child: LiveDataBuilder<List<TableColumn>>(
data: _columns,
builder: (context, columns) => XRawTable<int>(
columns: columns,
items: items,
defaultColumnWidth: const FixedColumnWidth(kMinInteractiveDimension * 3),
rowDecorator: XRawTable.oddRowDecorator(),
modules: [
TableSelectionModule<int>(keyOf: (item) => '$item', multipleSelection: _selection),
TableActionsModule<int>(
actions: [
TableAction<int>(
icon: const Icon(Icons.info_outline),
tooltip: 'Show',
onAction: (item) =>
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Item $item'))),
),
],
),
TableSortFilterModule<int>(sortOptions: _sortOptions, filterOptions: _filterOptions),
ColumnSwapModule<int>(onSwap: _moveColumn),
],
placeholder: (context) => const Center(child: Text('No items')),
rowBuilder: (context, row, item) => [for (final column in columns) Text('${column.id}$item')],
),
),
),
),
),
),
),
);
}