Flutter Table Plus

pub version license Flutter platforms

A highly customizable, type-safe Flutter table widget with synchronized scrolling, sorting, selection, editing, and more.

Flutter Table Plus Demo


✨ Features

Feature Description
Type-Safe Generics Works with any data model <T> — no more Map<String, dynamic>
Synchronized Scrolling Header and body scroll together seamlessly
Sorting Multi-state column sorting (ascending ↔ descending ↔ none)
Selection Single or multiple row selection with checkboxes
Inline Editing Click-to-edit cells with auto-save
Column Reordering Drag-and-drop columns, drop on empty space to move to last
Column Resizing Drag header edges to resize columns with min/max constraints and width persistence
Auto-Fit Columns Double-tap resize handle to auto-fit, with custom override callback
Stretch Last Column Last column fills remaining space when all columns are fixed
Drag Selection Mouse drag to select row ranges with auto-scroll and a configurable rubber band rectangle (Finder/Explorer-style marquee)
Merged Rows Group rows with custom merged content
Hover Buttons Action buttons on row hover
Dynamic Row Heights Support for variable height rows
Smart Tooltips Text, widget, and whole-row tooltips, anchored beside the widget or beside the cursor
Dim Rows Style inactive rows differently
Scale / Zoom Ctrl/Cmd+wheel zoom with platform-aware modifier key, scroll-safe physics, automatic position correction, and optional blockModifierScroll control
Deep Theming 8 nested theme classes for complete customization
Minimal Dependencies Only just_tooltip and flutter_checkbox

📦 Installation

dependencies:
  flutter_table_plus: ^2.15.3
flutter pub get

🚀 Quick Start

1. Define Your Data Model

class User {
  final String id;
  final String name;
  final String email;
  final int age;

  const User({
    required this.id,
    required this.name,
    required this.email,
    required this.age,
  });
}

2. Create the Table

import 'package:flutter_table_plus/flutter_table_plus.dart';

final columns = TableColumnsBuilder<User>()
  ..addColumn('name', TablePlusColumn(
    key: 'name',
    label: 'Name',
    order: 1,
    width: 150,
    valueAccessor: (user) => user.name,
    sortable: true,
  ))
  ..addColumn('email', TablePlusColumn(
    key: 'email',
    label: 'Email',
    order: 2,
    width: 200,
    valueAccessor: (user) => user.email,
  ))
  ..addColumn('age', TablePlusColumn(
    key: 'age',
    label: 'Age',
    order: 3,
    width: 80,
    valueAccessor: (user) => user.age,
    sortable: true,
  ));

final users = [
  User(id: '1', name: 'John Doe', email: 'john@example.com', age: 28),
  User(id: '2', name: 'Jane Smith', email: 'jane@example.com', age: 34),
];

FlutterTablePlus<User>(
  columns: columns.build(),
  data: users,
  rowId: (user) => user.id,  // Unique identifier for each row

  // Sorting
  sortColumnKey: _sortColumn,
  sortDirection: _sortDirection,
  onSort: (columnKey, direction) {
    setState(() {
      _sortColumn = columnKey;
      _sortDirection = direction;
      // Sort your data here
    });
  },

  // Selection
  isSelectable: true,
  selectionMode: SelectionMode.multiple,
  selectedRows: _selectedRows,
  onRowSelectionChanged: (rowId, isSelected) {
    setState(() {
      isSelected ? _selectedRows.add(rowId) : _selectedRows.remove(rowId);
    });
  },
)

3. Persist Column Widths

Save and restore user-resized column widths across sessions:

FlutterTablePlus<User>(
  columns: columns.build(),
  data: users,
  rowId: (user) => user.id,
  resizable: true,

  // Restore saved widths (reacts to changes — safe with Riverpod watch)
  initialResizedWidths: savedWidths, // e.g. {'name': 200, 'email': 150}

  // Save widths when user resizes
  onColumnResized: (columnKey, newWidth) {
    savedWidths[columnKey] = newWidth;
    // Persist to DB / SharedPreferences / etc.
  },
)

💡 Core Philosophy

Flutter Table Plus follows a UI-only, data-agnostic design:

  • You own your data — The package never stores or mutates your data
  • Callback-driven — All interactions flow through callbacks you control
  • State management agnostic — Works with setState, Provider, Riverpod, Bloc, etc.
  • Maximum flexibility — No assumptions about your data structure or business logic
// You handle sorting
onSort: (columnKey, direction) {
  // Sort your data however you want
  _myData.sort(...);
}

// You handle selection
onRowSelectionChanged: (rowId, isSelected) {
  // Update your selection state
  _selectedIds.add(rowId);
}

// You handle editing
onCellChanged: (row, columnKey, rowIndex, oldValue, newValue) {
  // Update your data model
  _myData[rowIndex] = row.copyWith(name: newValue);
}

📖 Documentation

Guide Description
Features Guide Sorting, Selection, Editing, Merged Rows, Hover Buttons, and more
Theming Guide Complete theming reference with all 8 theme classes
Migration Guide Migrating from v1.x (Map) to v2.x (Generic<T>)


📄 License

MIT License — see LICENSE for details.

Libraries

flutter_table_plus
A highly customizable and efficient table widget for Flutter.