flutterx_table 1.2.3
flutterx_table: ^1.2.3 copied to clipboard
Flutter high customizable Table full of features including selection, sorting, actions, etc...
example/lib/main.dart
import 'dart:math';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutterx_live_data/flutterx_live_data.dart';
import 'package:flutterx_table/flutterx_table.dart';
import 'package:flutterx_utils/flutterx_utils.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutterx Table Demo',
theme: ThemeData(primarySwatch: Colors.blueGrey),
home: const TableExample());
}
class TableExample extends StatefulWidget {
const TableExample({super.key});
@override
State<TableExample> createState() => _TableExampleState();
}
class _TableExampleState extends State<TableExample> with ObserverMixin, StateObserver {
static const letters = 'ABCDEFGHIKLMNOP'; // QRSTUVWXYZ
static final columns = letters.split('').map((id) => TableColumn(id: id, label: Text(id))).toList(growable: false);
final MutableLiveData<SortOptions?> _sortOptions = MutableLiveData();
final List<int> _allItems = List.generate(189, (index) => index + 1);
final LiveList<int> _items = LiveList();
final LiveSet<int> _selection = LiveSet();
final ScrollController _controllerX = ScrollController();
final ScrollController _controllerY = ScrollController();
late final MutableLiveData<PageInfo> _pageInfo =
MutableLiveData(value: PageInfo.of(pageSize: 10, itemsCount: _allItems.length));
@override
void registerObservers() => observe2<PageInfo, SortOptions?>(_pageInfo, _sortOptions, _computeItems);
void _computeItems(PageInfo page, SortOptions? sort) => _items.setTo(_allItems
.sorted((sort?.order ?? SortOrder.desc).comparator)
.sublist(page.startIndex, min(page.endIndex, _allItems.length)));
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text('Table example')),
body: SingleChildScrollView(child: Padding(padding: const EdgeInsets.all(32), child: _buildTable())));
@override
void dispose() {
_controllerX.dispose();
_controllerY.dispose();
super.dispose();
}
Widget _buildTable() => Card(
child: Column(crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: [
IntrinsicHeight(
child: ScrollableViewScrollbar.both(
controllerX: _controllerX,
controllerY: _controllerY,
child: ScrollableView(
controllerX: _controllerX,
controllerY: _controllerY,
matchContainerX: true,
child: XRawTable<int>(
border: const TableBorder(
horizontalInside: BorderSide(color: Colors.black38, width: .1),
bottom: BorderSide(color: Colors.black54, width: .1)),
columns: columns,
headingCellModifiers: const [
CellHeightModifier(height: 50, alignment: AlignmentDirectional.centerStart),
CellPaddingModifier(padding: EdgeInsets.symmetric(vertical: 18, horizontal: 18)),
SortArrowModifier(canClear: false),
HeadingCellTextStyleModifier(),
],
defaultColumnWidth: const FixedColumnWidth(kMinInteractiveDimension * 5),
actions: TableActions<int>(actions: [
TableAction<int>(icon: const Icon(Icons.delete), onAction: _items.remove),
TableAction<int>(
icon: const Icon(Icons.copy), onAction: (item) => _items.insert(item, item)),
]),
sortOptions: _sortOptions,
selection: TableSelection<int, int>(
primaryKey: (item) => item,
removeNonExistingItems: false,
// selectionOverride: (item) => item.isEven ? (item ~/ 2).isEven : null,
selection: _selection),
items: _items,
rowBuilder: (context, index, item) {
final color = Colors.primaries[index % Colors.primaries.length];
return List.generate(
columns.length,
(col) =>
Text('${columns[col].id.toUpperCase()} $item', style: TextStyle(color: color)));
})))),
PagingIndicatorLayout(
pageInfo: _pageInfo,
scrollable: true,
rowsPerPageIndicator: const RowsPerPageIndicator(availableRowsPerPage: {5, 10, 25, 50}),
pageIndicator: const PagingIndexIndicator()),
]),
);
// LiveDataBuilder<Set>(
// data: _selection,
// builder: (context, selection) => DataTable(
// sortColumnIndex: 2,
// columns: columns
// .map((e) => DataColumn(onSort: (index, ascending) {}, label: e.child!))
// .toList(growable: false),
// onSelectAll: (value) => value ?? false
// ? _selection.setTo(_items.map((item) => item))
// : _selection.clear(),
// rows: items.mapIndexed((index, item) {
// final color = Colors.primaries[index % Colors.primaries.length];
// return DataRow(
// selected: _selection.contains(item),
// onSelectChanged: (value) =>
// value ?? false ? _selection.add(item) : _selection.remove(item),
// cells: List.generate(
// columns.length,
// (col) => DataCell(Padding(
// padding: const EdgeInsets.all(8),
// child: Text('${columns[col].id.toUpperCase()} $item',
// style: TextStyle(color: color))))));
// }).toList(growable: false))) ??
}