Skip to main content

TableAppi

A powerful and flexible table widget for displaying structured data with support for sorting, filtering, pagination, and custom cell rendering.

Features

  • Dynamic Data Display: Display data from various sources with automatic updates
  • Sorting: Click column headers to sort data ascending/descending
  • Filtering: Built-in search and filter capabilities
  • Pagination: Handle large datasets with pagination controls
  • Custom Cell Rendering: Customize how individual cells are displayed
  • Row Selection: Single or multiple row selection support
  • Responsive Design: Adapts to different screen sizes
  • Loading States: Built-in loading indicators for async data

Usage

Basic Usage

TableAppi(
columns: [
TableColumn(key: 'name', title: 'Name'),
TableColumn(key: 'age', title: 'Age'),
TableColumn(key: 'email', title: 'Email'),
],
data: [
{'name': 'John Doe', 'age': 30, 'email': 'john@example.com'},
{'name': 'Jane Smith', 'age': 25, 'email': 'jane@example.com'},
],
)

Advanced Usage

TableAppi(
columns: tableColumns,
data: tableData,
isLoading: _isLoading,
enableSorting: true,
enableFiltering: true,
enablePagination: true,
pageSize: 10,
onRowTap: (rowData) => _handleRowTap(rowData),
onSelectionChanged: (selectedRows) => _handleSelection(selectedRows),
customCellBuilder: (column, value, rowData) => _buildCustomCell(column, value, rowData),
)

Parameters

NameTypeDescriptionDefault
columnsList<TableColumn>Required. Column definitions for the table-
dataList<Map<String, dynamic>>Required. Data to display in the table-
isLoadingbool?Whether to show loading indicatorfalse
enableSortingbool?Enable column sortingtrue
enableFilteringbool?Enable data filteringtrue
enablePaginationbool?Enable paginationfalse
pageSizeint?Number of rows per page10
currentPageint?Current page number (0-indexed)0
onRowTapFunction(Map<String, dynamic>)?Callback when a row is tappednull
onSelectionChangedFunction(List<Map<String, dynamic>>)?Callback when selection changesnull
customCellBuilderWidget Function(TableColumn, dynamic, Map<String, dynamic>)?Custom cell buildernull
headerStyleTextStyle?Style for header textTheme dependent
cellStyleTextStyle?Style for cell textTheme dependent
headerBackgroundColorColor?Background color for headerColors.grey.shade100
alternateRowColorColor?Background color for alternate rowsColors.grey.shade50
borderColorColor?Color of table bordersColors.grey.shade300
selectedRowColorColor?Background color for selected rowsColors.blue.shade100
hoverColorColor?Color when hovering over rowsColors.grey.shade200
multiSelectbool?Allow multiple row selectionfalse
showCheckboxesbool?Show selection checkboxesfalse
emptyMessageString?Message to show when no data'No data available'
searchPlaceholderString?Placeholder text for search field'Search...'

TableColumn Model

class TableColumn {
final String key;
final String title;
final bool sortable;
final bool filterable;
final double? width;
final TextAlign? alignment;
final Widget Function(dynamic value, Map<String, dynamic> rowData)? cellBuilder;

TableColumn({
required this.key,
required this.title,
this.sortable = true,
this.filterable = true,
this.width,
this.alignment = TextAlign.left,
this.cellBuilder,
});
}

Best Practices

  1. Performance: Use pagination for large datasets (>100 rows)
  2. Column Width: Set appropriate widths for columns to prevent overflow
  3. Custom Cells: Use custom cell builders for complex data types
  4. Loading States: Always show loading indicators for async operations
  5. Empty States: Provide meaningful messages when no data is available
  6. Accessibility: Ensure proper semantic labels for screen readers
  7. Responsive: Consider horizontal scrolling for tables with many columns

Examples

Simple Data Table

TableAppi(
columns: [
TableColumn(key: 'id', title: 'ID', width: 60),
TableColumn(key: 'name', title: 'Product Name'),
TableColumn(key: 'price', title: 'Price', alignment: TextAlign.right),
TableColumn(key: 'stock', title: 'Stock', alignment: TextAlign.center),
],
data: products,
)

Table with Custom Cells

TableAppi(
columns: [
TableColumn(key: 'avatar', title: 'Avatar', width: 80),
TableColumn(key: 'name', title: 'Name'),
TableColumn(key: 'status', title: 'Status'),
TableColumn(key: 'actions', title: 'Actions', sortable: false),
],
data: users,
customCellBuilder: (column, value, rowData) {
switch (column.key) {
case 'avatar':
return CircleAvatar(
backgroundImage: NetworkImage(value),
radius: 20,
);
case 'status':
return Chip(
label: Text(value),
backgroundColor: value == 'Active' ? Colors.green : Colors.red,
);
case 'actions':
return Row(
children: [
IconButton(
icon: Icon(Icons.edit),
onPressed: () => _editUser(rowData),
),
IconButton(
icon: Icon(Icons.delete),
onPressed: () => _deleteUser(rowData),
),
],
);
default:
return Text(value.toString());
}
},
)

Paginated Table with Selection

TableAppi(
columns: tableColumns,
data: currentPageData,
enablePagination: true,
pageSize: 20,
currentPage: _currentPage,
multiSelect: true,
showCheckboxes: true,
onSelectionChanged: (selectedRows) {
setState(() {
_selectedItems = selectedRows;
});
},
onPageChanged: (page) {
setState(() {
_currentPage = page;
_loadPageData(page);
});
},
)

Filterable and Sortable Table

TableAppi(
columns: [
TableColumn(key: 'date', title: 'Date', sortable: true),
TableColumn(key: 'transaction', title: 'Transaction', filterable: true),
TableColumn(key: 'amount', title: 'Amount', sortable: true, alignment: TextAlign.right),
],
data: transactions,
enableSorting: true,
enableFiltering: true,
onSortChanged: (column, ascending) {
_sortData(column, ascending);
},
onFilterChanged: (filters) {
_filterData(filters);
},
)