DataTable2#
Enhanced data table for Flet that adds sticky headers, fixed rows/columns, and other UX improvements via the flet-datatable2 extension.
It wraps the Flutter data_table_2 package.
Platform Support#
| Platform | Windows | macOS | Linux | iOS | Android | Web |
|---|---|---|---|---|---|---|
| Supported | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Usage#
Add flet-datatable2 to your project dependencies:
Examples#
Example 1#
import flet as ft
import flet_datatable2 as fdt
def main(page: ft.Page):
page.add(
fdt.DataTable2(
empty=ft.Text("This table is empty."),
columns=[
fdt.DataColumn2(label=ft.Text("First name")),
fdt.DataColumn2(label=ft.Text("Last name")),
fdt.DataColumn2(label=ft.Text("Age"), numeric=True),
],
),
)
if __name__ == "__main__":
ft.run(main)
Example 2#
from dataclasses import dataclass
import flet as ft
import flet_datatable2 as ftd
@dataclass
class Dessert:
name: str
calories: float
fat: float
carbs: float
protein: float
sodium: float
calcium: float
iron: float
desserts = [
Dessert("Frozen Yogurt", 159, 6.0, 24, 4.0, 87, 14, 1),
Dessert("Ice Cream Sandwich", 237, 9.0, 37, 4.3, 129, 8, 1),
Dessert("Eclair", 262, 16.0, 24, 6.0, 337, 6, 7),
Dessert("Cupcake", 305, 3.7, 67, 4.3, 413, 3, 8),
Dessert("Gingerbread", 356, 16.0, 49, 3.9, 327, 7, 16),
Dessert("Jelly Bean", 375, 0.0, 94, 0.0, 50, 0, 0),
Dessert("Lollipop", 392, 0.2, 98, 0.0, 38, 0, 2),
Dessert("Honeycomb", 408, 3.2, 87, 6.5, 562, 0, 45),
Dessert("Donut", 452, 25.0, 51, 4.9, 326, 2, 22),
Dessert("Apple Pie", 518, 26.0, 65, 7.0, 54, 12, 6),
Dessert("Frozen Yougurt with sugar", 168, 6.0, 26, 4.0, 87, 14, 1),
Dessert("Ice Cream Sandwich with sugar", 246, 9.0, 39, 4.3, 129, 8, 1),
Dessert("Eclair with sugar", 271, 16.0, 26, 6.0, 337, 6, 7),
Dessert("Cupcake with sugar", 314, 3.7, 69, 4.3, 413, 3, 8),
Dessert("Gingerbread with sugar", 345, 16.0, 51, 3.9, 327, 7, 16),
Dessert("Jelly Bean with sugar", 364, 0.0, 96, 0.0, 50, 0, 0),
Dessert("Lollipop with sugar", 401, 0.2, 100, 0.0, 38, 0, 2),
Dessert("Honeycomb with sugar", 417, 3.2, 89, 6.5, 562, 0, 45),
Dessert("Donut with sugar", 461, 25.0, 53, 4.9, 326, 2, 22),
Dessert("Apple pie with sugar", 527, 26.0, 67, 7.0, 54, 12, 6),
Dessert("Frozen yougurt with honey", 223, 6.0, 36, 4.0, 87, 14, 1),
Dessert("Ice Cream Sandwich with honey", 301, 9.0, 49, 4.3, 129, 8, 1),
Dessert("Eclair with honey", 326, 16.0, 36, 6.0, 337, 6, 7),
Dessert("Cupcake with honey", 369, 3.7, 79, 4.3, 413, 3, 8),
Dessert("Gingerbread with honey", 420, 16.0, 61, 3.9, 327, 7, 16),
Dessert("Jelly Bean with honey", 439, 0.0, 106, 0.0, 50, 0, 0),
Dessert("Lollipop with honey", 456, 0.2, 110, 0.0, 38, 0, 2),
Dessert("Honeycomb with honey", 472, 3.2, 99, 6.5, 562, 0, 45),
Dessert("Donut with honey", 516, 25.0, 63, 4.9, 326, 2, 22),
Dessert("Apple pie with honey", 582, 26.0, 77, 7.0, 54, 12, 6),
]
def main(page: ft.Page):
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
def handle_row_selection_change(e: ft.Event[ftd.DataRow2]):
e.control.selected = not e.control.selected
e.control.update()
def sort_column(e: ft.DataColumnSortEvent):
sorters = [
lambda d: d.name.lower(),
lambda d: d.calories,
lambda d: d.fat,
lambda d: d.carbs,
lambda d: d.protein,
lambda d: d.sodium,
lambda d: d.calcium,
lambda d: d.iron,
]
table.rows = get_data_rows(
sorted(desserts, key=sorters[e.column_index], reverse=not e.ascending)
)
table.sort_column_index = e.column_index
table.sort_ascending = e.ascending
table.update()
def get_data_rows(data: list[Dessert]) -> list[ftd.DataRow2]:
rows = []
for dessert in data:
rows.append(
ftd.DataRow2(
specific_row_height=50,
on_select_change=handle_row_selection_change,
cells=[
ft.DataCell(content=str(dessert.name)),
ft.DataCell(content=str(dessert.calories)),
ft.DataCell(content=str(dessert.fat)),
ft.DataCell(content=str(dessert.carbs)),
ft.DataCell(content=str(dessert.protein)),
ft.DataCell(content=str(dessert.sodium)),
ft.DataCell(content=str(dessert.calcium)),
ft.DataCell(content=str(dessert.iron)),
],
)
)
return rows
page.add(
table := ftd.DataTable2(
show_checkbox_column=True,
expand=True,
column_spacing=0,
heading_row_color=ft.Colors.SECONDARY_CONTAINER,
horizontal_margin=12,
sort_ascending=True,
bottom_margin=10,
min_width=600,
on_select_all=lambda e: print("All selected"),
rows=get_data_rows(desserts),
columns=[
ftd.DataColumn2(
label="Name",
size=ftd.DataColumnSize.L,
on_sort=sort_column,
heading_row_alignment=ft.MainAxisAlignment.START,
),
ftd.DataColumn2(
label="Calories",
on_sort=sort_column,
numeric=True,
heading_row_alignment=ft.MainAxisAlignment.END,
),
ftd.DataColumn2(label="Fat", numeric=True, on_sort=sort_column),
ftd.DataColumn2(label="Carbs", numeric=True, on_sort=sort_column),
ftd.DataColumn2(label="Protein", numeric=True, on_sort=sort_column),
ftd.DataColumn2(label="Sodium", numeric=True, on_sort=sort_column),
ftd.DataColumn2(label="Calcium", numeric=True, on_sort=sort_column),
ftd.DataColumn2(label="Iron", numeric=True, on_sort=sort_column),
],
)
)
if __name__ == "__main__":
ft.run(main)
Description#
Inherits: DataTable
Provides sticky header row, scrollable data rows,
and additional layout flexibility with DataColumn2
and DataRow2.
Note
DataTable2 doesn't support
DataTable.data_row_min_height
and DataTable.data_row_max_height
properties present in the parent DataTable.
Use data_row_height instead.
Properties
-
bottom_margin(Number | None) –Adds space after the last row if set.
-
checkbox_alignment(Alignment) –Alignment of the checkbox.
-
columns(list[DataColumn2 | DataColumn]) –A list of table columns.
-
data_row_checkbox_theme(CheckboxTheme | None) –Overrides theme of checkboxes in each data row.
-
data_row_height(Number | None) –Height of each data row.
-
data_row_max_height(None) – -
data_row_min_height(None) – -
empty(Control | None) –Placeholder control shown when there are no data rows.
-
fixed_columns_color(ColorValue | None) –Background color for sticky left columns.
-
fixed_corner_color(ColorValue | None) –Background color of the fixed top-left corner cell.
-
fixed_left_columns(int) –Number of sticky columns on the left. Includes checkbox column, if present.
-
fixed_top_rows(int) –Number of sticky rows from the top. Includes heading row by default.
-
heading_checkbox_theme(CheckboxTheme | None) –Overrides theme of the heading checkbox.
-
lm_ratio(Number) –Ratio of Large column width to Medium.
-
min_width(Number | None) –Minimum table width before horizontal scrolling kicks in.
-
rows(list[DataRow | DataRow2]) –A list of table rows.
-
show_heading_checkbox(bool) –Controls visibility of the heading checkbox.
-
sm_ratio(Number) –Ratio of Small column width to Medium.
-
sort_arrow_animation_duration(DurationValue) –Duration of sort arrow animation.
-
sort_arrow_icon(IconData) –Icon shown when sorting is applied.
-
sort_arrow_icon_color(ColorValue | None) –When set always overrides/preceeds default arrow icon color.
-
visible_horizontal_scroll_bar(bool | None) –Determines visibility of the horizontal scrollbar.
-
visible_vertical_scroll_bar(bool | None) –Determines visibility of the vertical scrollbar.
Properties#
bottom_margin
class-attribute
instance-attribute
#
bottom_margin: Number | None = None
Adds space after the last row if set.
checkbox_alignment
class-attribute
instance-attribute
#
Alignment of the checkbox.
data_row_checkbox_theme
class-attribute
instance-attribute
#
data_row_checkbox_theme: CheckboxTheme | None = None
Overrides theme of checkboxes in each data row.
data_row_height
class-attribute
instance-attribute
#
data_row_height: Number | None = None
Height of each data row.
data_row_max_height
class-attribute
instance-attribute
#
data_row_max_height: None = field(
init=False,
repr=False,
compare=False,
metadata={"skip": True},
)
data_row_min_height
class-attribute
instance-attribute
#
data_row_min_height: None = field(
init=False,
repr=False,
compare=False,
metadata={"skip": True},
)
empty
class-attribute
instance-attribute
#
empty: Control | None = None
Placeholder control shown when there are no data rows.
fixed_columns_color
class-attribute
instance-attribute
#
fixed_columns_color: ColorValue | None = None
Background color for sticky left columns.
fixed_corner_color
class-attribute
instance-attribute
#
fixed_corner_color: ColorValue | None = None
Background color of the fixed top-left corner cell.
fixed_left_columns
class-attribute
instance-attribute
#
fixed_left_columns: int = 0
Number of sticky columns on the left. Includes checkbox column, if present.
fixed_top_rows
class-attribute
instance-attribute
#
fixed_top_rows: int = 1
Number of sticky rows from the top. Includes heading row by default.
heading_checkbox_theme
class-attribute
instance-attribute
#
heading_checkbox_theme: CheckboxTheme | None = None
Overrides theme of the heading checkbox.
lm_ratio
class-attribute
instance-attribute
#
lm_ratio: Number = 1.2
Ratio of Large column width to Medium.
min_width
class-attribute
instance-attribute
#
min_width: Number | None = None
Minimum table width before horizontal scrolling kicks in.
rows
class-attribute
instance-attribute
#
A list of table rows.
show_heading_checkbox
class-attribute
instance-attribute
#
show_heading_checkbox: bool = True
Controls visibility of the heading checkbox.
sm_ratio
class-attribute
instance-attribute
#
sm_ratio: Number = 0.67
Ratio of Small column width to Medium.
sort_arrow_animation_duration
class-attribute
instance-attribute
#
sort_arrow_animation_duration: DurationValue = field(
default_factory=lambda: Duration(milliseconds=150)
)
Duration of sort arrow animation.
sort_arrow_icon
class-attribute
instance-attribute
#
sort_arrow_icon: IconData = ARROW_UPWARD
Icon shown when sorting is applied.
sort_arrow_icon_color
class-attribute
instance-attribute
#
sort_arrow_icon_color: ColorValue | None = None
When set always overrides/preceeds default arrow icon color.