tablex 0.7.4
tablex: ^0.7.4 copied to clipboard
A production-grade Flutter data grid with zero dependency on any third-party grid engine.
0.7.4 #
New features #
-
pageSizeSelectorBuilder— override the page-size dropdown — pass aTablexPageSizeSelectorBuildercallback toTablexConsumer,Tablex.lazyPaged, orTablexPaginationFooterto replace the built-inDropdownButtonwith any widget. The callback receives the current page size, the list of available options, and theonChangedcallback.TablexConsumer<Employee>( pageSizeSelectorBuilder: (context, current, options, onChange) => SegmentedButton<int>( segments: options.map((n) => ButtonSegment(value: n, label: Text('$n'))).toList(), selected: {current}, onSelectionChanged: (s) => onChange(s.first), ), ) -
TablexThemeData.pageSizeSelectorIcon— theme the dropdown icon — setpageSizeSelectorIconon yourTablexThemeDatato customise the icon shown on the default page-size selector. Defaults toIcons.unfold_more_roundedwhen null.
Bug fixes #
-
Page-size selector now hidden when no rows are loaded — the selector was always visible because
totalPagesinitialises to1before any fetch. The guard now checkstotalRows > 0, so the selector is correctly hidden on empty results, error states, and initial load. -
TablexPageSizeSelectorbrokenicon:fixed — the icon field had a syntax error (icon: ,) that caused a compile failure. The icon is now rendered fromTablexThemeData.pageSizeSelectorIcon(or theIcons.unfold_more_roundedfallback).
0.7.3 #
Bug fixes #
fetchWithSorting: falsenow sorts loaded rows in place forlazyPagedandinfinite— previously, tapping a sort header in either server-side variant withfetchWithSorting: falsewas a silent no-op: the re-fetch was correctly skipped but the visible rows were never reordered. The fix mirrors what thestaticvariant has always done — the currently-loaded rows are sorted in memory using the same comparator (extractValue→Comparable.compareTowith string fallback) and replaced viareplaceRows. ForlazyPagedthis sorts the current page; forinfiniteit sorts the loaded window. Full-dataset ordering still requires a server-side sort (fetchWithSorting: true).
0.7.2 #
Bug fixes #
-
Cursor page indicator updates immediately on navigation —
_CursorPageIndicatornow reflects the new page number as soon as the user taps Previous / Next / Go-to-page, before the async fetch completes. Previously the indicator could lag behind until the controller'sListenableBuilderfired. Fixed by callingsetStatesynchronously in all three cursor navigation methods. -
Page jump indicator no longer shows "of N" — the editable page number field in the default footer now stands alone without the
of [totalPages]suffix. Navigation and page-jump still work identically.
Example #
- Cursor-based pagination in the Paged tab —
_fakePagedFetchnow returnsnextCursor/prevCursor(offset encoded as an opaque string), activating cursor mode in the footer. This demonstrates the_CursorPageIndicator, cursor history management, and back-navigation from cache without a re-fetch.
0.7.1 #
New features #
-
TablexConsumer.filterBarBuilder— custom filter bar override — pass afilterBarBuildercallback to replace the built-in chip-dialog filter bar with any widget. The callback receives the currentList<TablexActiveFilter>, the typedTablexController<T>, and theBuildContext, so you can readcontroller.state.query.paramsand callcontroller.setParam(...)directly without going through the dialog.TablexConsumer<Employee>( filterBarBuilder: (context, filters, controller) => MyInlineFilterRow( filters: filters, onToggle: (key, value) => controller.setParam(key, value), ), )Return
SizedBox.shrink()to suppress the bar entirely while keeping fetch metadata wired up.
0.7.0 #
Breaking changes #
-
TablexPdfConfig.rtlremoved — RTL is now auto-detected — thertl: boolfield has been removed fromTablexPdfConfig. The PDF exporter now inspects the first non-whitespace code point of every header and cell value and switches topw.TextDirection.rtlautomatically when RTL content is found (the same Unicode scanning used by grid cells since 0.6.0). Remove anyrtl:argument from existingTablexPdfConfigcalls — the result will be identical or better.Before:
controller.pdfConfig = TablexPdfConfig( fontData: await rootBundle.load('assets/fonts/Cairo-Regular.ttf'), rtl: true, );After:
controller.pdfConfig = TablexPdfConfig( fontData: await rootBundle.load('assets/fonts/Cairo-Regular.ttf'), );
New features #
-
TablexPdfConfigaccepts pre-builtpw.Font— two new optional fieldsfont(pw.Font?) andfontBold(pw.Font?) accept a pre-built font directly, for example fromPdfGoogleFontsin theprintingpackage. They take precedence overfontData/fontBoldDatawhen both are provided.// Using bundled asset bytes (no pdf import needed): controller.pdfConfig = TablexPdfConfig( fontData: await rootBundle.load('assets/fonts/Cairo-Regular.ttf'), fontBoldData: await rootBundle.load('assets/fonts/Cairo-Bold.ttf'), ); // Using PdfGoogleFonts (printing package already imported): controller.pdfConfig = TablexPdfConfig( font: await PdfGoogleFonts.cairoRegular(), fontBold: await PdfGoogleFonts.cairoBold(), );
0.6.0 #
New features #
- Automatic RTL text detection in grid cells — Arabic, Hebrew, and other right-to-left scripts now render correctly in grid cells even when the host app's directionality is LTR. No configuration is needed. Each cell independently:
- Detects whether its text starts with an RTL Unicode character (Arabic U+0600–U+06FF, Hebrew U+0590–U+05FF, Arabic Supplement, NKo, Arabic Presentation Forms, etc.) by inspecting the first non-whitespace code point — zero overhead per cell.
- Sets
textDirection: TextDirection.rtlon theText/SelectableTextwidget so Flutter lays the text out right-to-left and clips overflow on the correct side. - Switches alignment to
TextAlign.rightfor RTL content when the column uses the defaultTextAlign.start, so Arabic/Hebrew text sits at the right edge of the cell rather than the left. - Mixed rows (some cells LTR, some RTL) are handled correctly — each cell is resolved independently.
0.5.9 #
Breaking changes #
-
TablexPdfConfigAPI simplified — nopdfpackage import required —font/fontBold(pw.Font) andtextDirection(pw.TextDirection) have been replaced withfontData/fontBoldData(ByteData) andrtl(bool). The library now constructspw.Fontinternally, so callers never need to importpackage:pdf/widgets.dart.Before:
import 'package:pdf/widgets.dart' as pw; controller.pdfConfig = TablexPdfConfig( font: pw.Font.ttf(await rootBundle.load('assets/fonts/Cairo-Regular.ttf')), fontBold: pw.Font.ttf(await rootBundle.load('assets/fonts/Cairo-Bold.ttf')), textDirection: pw.TextDirection.rtl, );After:
controller.pdfConfig = TablexPdfConfig( fontData: await rootBundle.load('assets/fonts/Cairo-Regular.ttf'), fontBoldData: await rootBundle.load('assets/fonts/Cairo-Bold.ttf'), rtl: true, );
0.5.8 #
New features #
TablexPdfConfig— custom font and RTL support for PDF exports — the built-in PDF fonts (Helvetica / Times) only cover Latin characters; non-Latin scripts (Arabic, Hebrew, CJK, etc.) require a font that includes the relevant glyphs.TablexPdfConfigaccepts rawByteDatafromrootBundle.load()so nopdfpackage import is needed. Set it once on the controller and all export paths — including toolbar buttons — use it automatically. The per-callpdfConfigparameter onexportToPdf/exportSelectedToPdfis available for one-off overrides.fontData(ByteData?) — TTF font for cell content.fontBoldData(ByteData?) — TTF font for column headers; falls back tofontDatawhennull.rtl(bool) — set totruefor right-to-left scripts. Text direction and numeric column alignment are adjusted automatically.
controller.pdfConfig = TablexPdfConfig( fontData: await rootBundle.load('assets/fonts/Cairo-Regular.ttf'), fontBoldData: await rootBundle.load('assets/fonts/Cairo-Bold.ttf'), rtl: true, );
0.5.7 #
Breaking changes #
exportFormattersignature changed fromdynamictoTRow— the type ofTablexColumnBase.exportFormatterhas changed fromString Function(dynamic rawValue)?toString Function(TRow row)?. This gives full access to the typed row object rather than just the raw cell value, enabling export strings derived from multiple fields or computed values. Update any existingexportFormattercallbacks to accept the row type instead ofdynamic.
0.5.6 #
New features #
-
Per-column
hideIfEmptyflag — sethideIfEmpty: trueon anyTablexColumnto automatically hide that column when every loaded row has a null or empty value for it. The column reappears as soon as any row provides a non-empty value. Complements the existing grid-levelhideEmptyColumnsflag, which applies the same behaviour to all columns at once. -
exportFormatteronTablexColumnBase— an optionalString Function(TRow row)that overrides the default export string for CSV, Excel, and PDF. Receives the full typed row object so you can derive the export value from any combination of fields. Resolution order:exportFormatter→ columnformatter→Enum.name(automatic, no config needed) →toString().
Bug fixes #
-
Column flicker with
hideEmptyColumns/hideIfEmptywhile paging — columns no longer disappear and reappear as the user pages through data. Visibility is now computed from an accumulated_seenNonEmptyFieldsset that only ever grows within a session, so a column stays visible once it has been shown. -
Header / body column misalignment with
hideIfEmpty—TablexBodywas readingstate.hiddenColumnFieldsinternally, bypassing the widget-levelhiddenFieldsset (which includes the empty-column logic). The computedhiddenFieldsis now passed intoTablexBodydirectly, keeping the header and body in sync. -
Action columns included in exports — columns with
type: TablexColumnType.actionare now excluded from CSV, Excel, and PDF exports. -
Enum values exported with class prefix — enum cell values (e.g.
EmployeeStatus.active) are now exported as their short.name('active') automatically, with no column configuration required. -
Cell renderers now accept nullable values — all built-in renderers (
text,currency,dateTime,boolean,statusChip,twoLine,avatarTwoLine,link,identifier,copyableText) have been updated to acceptTValue?. Renderers returnSizedBox.shrink()fornullvalues; thebooleanrenderer uses a tristateCheckboxfornull.
Refactoring #
-
Split
tablex_widget.dartinto part files — the 955-line file is now broken into three focusedpart offiles:_tablex_state.dart—_TablexState<T>+_InfiniteLoadingBar_selection_summary_header.dart—_SelectionSummaryHeader<T>+_SelectionSummaryHeaderState<T>_tablex_state_mixin.dart— unchanged, already extractedtablex_widget.dartretains only the_TablexVariantenum and theTablexwidget declaration (~383 lines).
-
Split
controller.dartinto part files — the 692-line controller is now broken into five focusedpart offiles:_controller_rows.dart— row CRUD (replaceRows,appendRows,prependRows,removeRow*,clearRows,getRow*,rows,rowCount)_controller_query.dart— query/pagination/sort/filter and loading/meta/error state_controller_selection.dart— selection (selectRow,deselectRow,toggleRowSelection,selectAll,clearSelection,selectedRows,isSelected)_controller_columns.dart— column visibility, width, order, frozen pinning, and inline editing_controller_export.dart— CSV/Excel/PDF import/export (unchanged)controller.dartretains only the class skeleton — fields, constructor,_checkDisposed,_notify, anddispose(~129 lines).
0.5.2 #
New features #
- Select-all / deselect-all checkbox in the selection summary bar — in
multipleselection mode a tristateCheckboxis shown at the leading edge of the bar. The checkbox is checked when every loaded row is selected, indeterminate when some are selected, and tapping it toggles between select-all and clear-selection. It follows the grid'sTablexCheckboxTheme(active colour, check colour, border, shape, and size) for visual consistency with the row and header checkboxes._SelectionSummaryHeader(insideTablex) reads the checkbox theme from the resolvedTablexThemeData.TablexSelectionSummaryBar(standalone widget) gains two new optional params —totalCountandonSelectAll— to opt into the same behaviour from outside the grid.TablexConsumerautomatically wirestotalCountandonSelectAllwhenselectionModeismultiple.
API additions #
| Symbol | Kind | Notes |
|---|---|---|
TablexSelectionSummaryBar.totalCount |
param | Total row count; determines the tristate checkbox value |
TablexSelectionSummaryBar.onSelectAll |
param | Callback to select all rows; presence enables the checkbox |
0.5.1 #
Documentation #
- Updated
README.mdto cover PDF export, export-selected-rows, selectable cell text, theme-level empty-cell placeholder, and selection summary bar colour. - Bumped the
Getting startedversion constraint to^0.5.1.
0.5.0 #
New features #
-
PDF export —
TablexController.exportToPdf(columns)andexportSelectedToPdf(columns)generate a styled.pdfbyte array. The page switches automatically to landscape when more than six visible columns are present;numberandcurrencycolumns are right-aligned; rows alternate between white and light-grey. Requires the newpdf: ^3.10.7dependency. -
Export selected rows — new controller methods
exportSelectedToCsv,exportSelectedToExcel, andexportSelectedToPdfserialise only the currently selected rows. The toolbar export buttons (CSV, Excel, PDF) automatically switch to selected-only mode when rows are selected — tooltip updates to show the count (e.g.'Export CSV (3 selected)'). The selection summary bar now shows CSV, Excel, and PDF icon buttons for the same purpose. -
Selectable cell text on web — cell text is rendered with
SelectableTexton web by default, allowing users to click-drag to copy values without leaving the grid. Controlled byTablexThemeData.enableTextSelection(defaults tokIsWeb; opt in on desktop by setting it totrue). Applies to all built-in text renderers:text,date,dateTime,twoLine,avatarTwoLine,currency, and the default type-based cell. Row tap and double-tap interactions are unaffected. -
Theme-level empty-cell placeholder —
TablexThemeData.emptyCellPlaceholdersets a grid-wide string shown fornullcell values (e.g.'N/A'), without having to configureTablexColumnBase.emptyCellPlaceholderon every column. Precedence: column-level → theme-level →'—'(whenshowEmptyAsDash) → blank. -
Themeable selection summary bar colour —
TablexThemeData.selectionSummaryBarColorcontrols the background of the selection summary bar. Defaults toColorScheme.surfaceContainerHighest. BothTablexSelectionSummaryBar(standalone) and the built-in_SelectionSummaryHeaderinsideTablexrespect this value.
API additions #
| Symbol | Kind | Notes |
|---|---|---|
TablexController.exportToPdf() |
method | All rows → PDF bytes (async) |
TablexController.exportSelectedToPdf() |
method | Selected rows → PDF bytes (async) |
TablexController.exportSelectedToCsv() |
method | Selected rows → CSV string |
TablexController.exportSelectedToExcel() |
method | Selected rows → .xlsx bytes |
Tablex.*.onExportSelectedCsv |
param | Override CSV export in the summary bar |
Tablex.*.onExportSelectedExcel |
param | Override Excel export in the summary bar |
Tablex.*.onExportSelectedPdf |
param | Override PDF export in the summary bar |
TablexConsumer.onExportSelectedCsv |
param | Same, for TablexConsumer |
TablexConsumer.onExportSelectedExcel |
param | Same, for TablexConsumer |
TablexConsumer.onExportSelectedPdf |
param | Same, for TablexConsumer |
TablexToolbar.onExportPdf |
param | Override PDF toolbar action |
TablexToolbar.exportPdfIcon |
param | Custom icon for the PDF button |
TablexSelectionSummaryBar.onExportSelectedPdf |
param | PDF button in standalone summary bar |
TablexThemeData.enableTextSelection |
field | Toggle SelectableText in cells |
TablexThemeData.emptyCellPlaceholder |
field | Grid-wide null-cell placeholder |
TablexThemeData.selectionSummaryBarColor |
field | Summary bar background colour |
TablexCellContext.enableTextSelection |
field | Readable by custom renderers |
Dependencies #
- Added
pdf: ^3.10.7.
0.4.0 #
New features #
-
Inline cell editing — set
enableEditing: trueon anyTablexColumnto make its cells editable. Double-tap a cell to enter edit mode; the grid renders a type-aware input widget by default:text/ default → auto-focusedTextFieldwith full text pre-selected.number/currency→ numeric keyboard, right-aligned text.boolean→ single-tap toggles the value immediately (no text input).- Custom → supply
editRendereron the column to replace the input with any widget (e.g. a dropdown, date picker, or colour swatch). - Commit with Enter or click-outside; cancel with Escape.
-
TablexColumn.onEditcallback — fired after the user commits an edit. Receives the original row object and the new typed value. The grid has already updated the cell display optimistically; use this callback to persist to your API or local state. -
TablexColumn.editRenderer— fully custom edit widget per column. Receives(BuildContext, TRow, TValue currentValue, onSubmit, onCancel). The grid wraps it in aFocusnode so Escape always cancels regardless of the widget used. -
TablexController.updateCell(rowIndex, field, newValue)— updates a single cell value in place without requiring a fullrowBuilder. Available for programmatic optimistic updates outside of inline editing. -
TablexThemeData.editInputDecoration— overrides theInputDecorationof the default text-field editor globally for a grid, without writing a per-columneditRenderer. -
Keyboard navigation in edit mode — while a cell is in edit mode, navigation keys move focus to the next cell without leaving the keyboard:
- Tab — commit and move to the next editable column; wraps to the first editable column of the next row.
- Shift+Tab — commit and move to the previous editable column; wraps to the last editable column of the previous row.
- ↓ Arrow Down — commit and move to the same column in the next row.
- ↑ Arrow Up — commit and move to the same column in the previous row.
- Arrow navigation scrolls the list automatically to keep the target cell visible.
TablexEditDirectionenum is exported for customeditRendererwidgets that want to implement the same shortcuts.
API additions #
| Symbol | Kind | Notes |
|---|---|---|
TablexColumn.onEdit |
callback | Typed (TRow, TValue) edit callback |
TablexColumn.editRenderer |
builder | Fully custom edit widget |
TablexColumnBase.handleEdit() |
method | Override to dispatch typed onEdit |
TablexColumnBase.buildEditCell() |
method | Override to supply custom edit UI |
TablexController.updateCell() |
method | Single-cell in-place update |
TablexThemeData.editInputDecoration |
field | Overrides default edit-field decoration |
TablexEditDirection |
enum | Tab / Shift+Tab / ↓ / ↑ navigation directions |
Example app #
- The I/O tab is now fully wired for inline editing:
Name(text field),Salary(numeric field),Department(dropdown viaeditRenderer), andManager(boolean toggle). Edits propagate back throughupdateRowso CSV/Excel exports reflect the latest values.
0.3.3 #
Documentation #
- Added iOS, macOS, and Web screenshots to
README.mdand registered them inpubspec.yamlunderscreenshots:so they appear in the pub.dev package carousel.
Example app #
- Removed explicit
id("kotlin-android")fromexample/android/app/build.gradle.kts— the Flutter Gradle Plugin now applies Kotlin internally, eliminating the KGP deprecation warning introduced in recent Flutter versions.
0.3.2 #
New features #
-
Cursor-based pagination —
Tablex.lazyPagednow supports opaque-cursor APIs alongside the existing offset-based mode. ReturnnextCursor(and optionallyprevCursor) from yourTablexFetchTaskand the footer switches modes automatically — no constructor flag required. Back-navigation is handled via an internal cursor history so APIs that only returnnextCursorstill support going back.TablexQuerygains acursorfield;TablexFetchResultgainsnextCursorandprevCursor.TablexPaginationInfogainsisCursorModeandhasNextPagefor customfooterBuilderimplementations. -
Redesigned pagination footer — the default footer UI has been replaced with a pill-based design: a 2 px loading strip at the top, windowed page pills (
[1] ··· [4][5][6] ··· [20]), and labelled← Previous/Next →buttons. In cursor mode the pills are replaced by aPage N(orPage N of M) indicator. TheenablePageJumpeditable-input mode is preserved. -
Default cell renderers per column type — columns without a
cellRenderernow render according to theirtype:boolean→ read-only checkbox,date/dateTime→ formatted date string,currency→ sign-aware coloured amount,number→ end-aligned text,id/identifier→ tap-to-copy monospace (unchanged). Plain text is still the fallback fortext,select, andaction.
Bug fixes #
file_pickerconstraint updated — bumped to^11.0.2.
Internal #
- Refactored
tablex_widget.dart: public API types (TablexLoadingBuilder,TablexErrorBuilder,TablexSelectionSummaryBuilder,TablexSelectionAction) moved totablex_types.dart; scroll sync, infinite-scroll, and sort logic extracted to_tablex_state_mixin.dartviapart of. - Refactored
controller.dart: CSV and Excel export/import logic moved to_controller_export.dartviapart of, keeping the reactiveChangeNotifiercore separate from serialization.
0.3.0 #
New features #
- Frozen / pinned columns — set
frozen: TablexColumnFrozen.startorfrozen: TablexColumnFrozen.endon anyTablexColumnto pin it to the left or right edge of the grid. Frozen columns remain visible while the user scrolls horizontally.- RTL-aware:
startpins to the right andendto the left in RTL locales. Shadow direction is computed fromDirectionality.of(context). - Vertical scroll is kept in sync with the main body via dedicated
ScrollControllers. Pointer scroll events and touch drag on frozen panels are forwarded to the main controller so the user can scroll from anywhere. - Sort and column resize work on frozen columns identical to scrollable columns. Drag-to-reorder is intentionally disabled for frozen columns.
- Column visibility (
hide: true) collapses a frozen panel entirely if all its columns are hidden. - Selection summary bar spans the full width of all three panels.
- RTL-aware:
0.2.1 #
Bug fixes #
- WASM compatibility — file import (
FilePicker.pickFiles) is now behind a conditional export sodart:iois never imported on web or WASM.dart.library.js_interoproutes to an HTML<input type="file">+FileReaderimplementation instead. - Formatting — all library files now pass
dart format. - Dependency lower-bound fix — tightened
excelconstraint to^4.0.6(the version that introducedTextCellValue.valueasTextSpan); the previous^4.0.0caused a type error underdart pub downgrade. - Updated
file_pickerto^11.0.0— aligns with the current stable release and migrates call sites from the removedFilePicker.platform.*instance methods to the newFilePicker.*static API.
0.2.0 #
New features #
TablexConsumer— high-level widget that wrapsTablex.lazyPagedwith a bordered container, optional title/filter header slots, automatic filter-chip bar, and controller lifecycle management.- Sliding-window infinite scroll —
Tablex.infinitenow accepts awindowPagesparameter. Old pages are evicted as new ones arrive; scroll-position compensation viajumpTokeeps the viewport stable. - Skeleton loading —
TablexLoadingBuilderpre-populates the grid with placeholder rows so a shimmer library (e.g. Skeletonizer) has real content to animate over, on bothlazyPagedandinfinitegrids. - Custom pagination footer —
footerBuilderonTablex.lazyPagedandTablexConsumerfully replaces the default footer.enablePageJumpmakes the page indicator an editable text field. TablexToolbar— drop-in toolbar with column-visibility management, CSV export (formula-injection protected), Excel export, CSV import, and Excel import. Each action can be overridden individually.prependRows/removeFirstRows/removeLastRowsonTablexController— used internally by the sliding-window but available for manual row management.- Sort race-condition guard — a generation counter on
Tablex.infiniteensures that in-flight fetch results are discarded when a sort or reset fires before they resolve.
Bug fixes #
- Fixed infinite-scroll first-page load using
appendRowsinstead ofreplaceRowsafter a sort reset, causing skeleton rows to persist above the sorted results. - Fixed header row being included in the skeleton loading scope, causing column headers to shimmer on re-fetch.
Tests #
- Added 13 unit tests for the sliding-window controller methods (
prependRows,removeFirstRows,removeLastRows). - Added 26 widget + unit tests covering
TablexQuery.copyWith, static sort (ascending, descending, clear, icons), lazy-paged fetch (initial query, sort re-fetch, error state, custom error widget), and infinite-scroll (skeleton replace, sort re-fetch, stale-result discard).
0.1.0 #
- Initial release.
- Four grid modes:
static,lazyPaged,infinite, andselect. - Built-in cell renderers:
identifier,twoLine,avatarTwoLine,currency,date,statusChip,actions. - Column resizing, sorting, and column-visibility manager.
- Three density presets:
compact,standard,comfortable. - Multi-row selection with customisable summary bar and bulk actions.
- Theming via
TablexThemeData. - i18n support via
slang.
