Files
StreamLens/Documentation/textual/datatable.md
noisedestroyers 36a576dc2c Enhanced Textual TUI with proper API usage and documentation
- Fixed DataTable row selection and event handling
- Added explicit column keys to prevent auto-generated keys
- Implemented row-to-flow mapping for reliable selection tracking
- Converted left metrics panel to horizontal top bar
- Fixed all missing FlowStats/EnhancedAnalysisData attributes
- Created comprehensive Textual API documentation in Documentation/textual/
- Added validation checklist to prevent future API mismatches
- Preserved cursor position during data refreshes
- Fixed RowKey type handling and event names

The TUI now properly handles flow selection, displays metrics in a compact top bar,
and correctly correlates selected rows with the details pane.
2025-07-27 18:37:55 -04:00

5.7 KiB

DataTable Widget API Reference

Overview

The DataTable widget displays tabular data with support for selection, scrolling, and styling.

Import

from textual.widgets import DataTable

Class Hierarchy

Widget → ScrollView → DataTable

Constructor

DataTable(
    *,
    show_header: bool = True,
    fixed_rows: int = 0,
    fixed_columns: int = 0,
    zebra_stripes: bool = False,
    header_height: int = 1,
    show_cursor: bool = True,
    cursor_foreground_priority: Literal["renderable", "css"] = "renderable",
    cursor_background_priority: Literal["renderable", "css"] = "renderable",
    cursor_type: CursorType = "cell",
    cell_padding: int = 1,
    name: str | None = None,
    id: str | None = None,
    classes: str | None = None,
    disabled: bool = False
)

Key Properties

Cursor Properties

  • cursor_row: int - Current cursor row (0-based)
  • cursor_column: int - Current cursor column (0-based)
  • cursor_coordinate: Coordinate - (row, column) tuple

Table Properties

  • rows: Mapping[RowKey, Row] - Dictionary of rows
  • columns: list[Column] - List of columns
  • row_count: int - Number of rows
  • column_count: int - Number of columns

Methods

Adding Data

# Add columns
add_column(label: TextType, *, width: int | None = None, key: str | None = None, default: CellType | None = None) -> ColumnKey

# Add multiple columns
add_columns(*labels: TextType) -> list[ColumnKey]

# Add a single row
add_row(*cells: CellType, height: int | None = 1, key: str | None = None, label: TextType | None = None) -> RowKey

# Add multiple rows
add_rows(rows: Iterable[Iterable[CellType]]) -> list[RowKey]

Modifying Data

# Update a cell
update_cell(row_key: RowKey, column_key: ColumnKey, value: CellType, *, update_width: bool = False) -> None

# Update cell at coordinate
update_cell_at(coordinate: Coordinate, value: CellType, *, update_width: bool = False) -> None

# Remove row
remove_row(row_key: RowKey) -> None

# Remove column  
remove_column(column_key: ColumnKey) -> None

# Clear all data
clear(columns: bool = False) -> Self

Navigation

# Move cursor
move_cursor(row: int | None = None, column: int | None = None, animate: bool = True, scroll: bool = True) -> None

# Scroll to coordinate
scroll_to(x: float | None = None, y: float | None = None, *, animate: bool = True, speed: float | None = None, duration: float | None = None, ...) -> None

Sorting

# Sort by column(s)
sort(*columns: ColumnKey | str, reverse: bool = False) -> Self

# Sort with custom key
sort(key: Callable[[Any], Any], *, reverse: bool = False) -> Self

Events

Selection Events

class RowSelected(Message):
    """Posted when a row is selected (Enter key)."""
    row_key: RowKey
    row_index: int

class CellSelected(Message):
    """Posted when a cell is selected."""
    coordinate: Coordinate
    cell_key: CellKey

class RowHighlighted(Message):
    """Posted when cursor highlights a row."""
    row_key: RowKey
    row_index: int

class CellHighlighted(Message):
    """Posted when cursor highlights a cell."""
    coordinate: Coordinate
    cell_key: CellKey

class ColumnHighlighted(Message):
    """Posted when cursor highlights a column."""
    column_key: ColumnKey
    column_index: int

Header Events

class HeaderSelected(Message):
    """Posted when a column header is clicked."""
    column_key: ColumnKey
    column_index: int
    label: Text

class RowLabelSelected(Message):
    """Posted when a row label is clicked."""
    row_key: RowKey
    row_index: int
    label: Text

Common Patterns

Creating a DataTable

class MyWidget(Widget):
    def compose(self) -> ComposeResult:
        yield DataTable(id="my-table")
    
    def on_mount(self) -> None:
        table = self.query_one("#my-table", DataTable)
        table.add_columns("Name", "Value", "Status")
        table.add_row("Item 1", "100", "Active", key="item_1")

Handling Selection

def on_data_table_row_highlighted(self, event: DataTable.RowHighlighted) -> None:
    # React to cursor movement
    self.selected_row = event.row_key

def on_data_table_row_selected(self, event: DataTable.RowSelected) -> None:
    # React to Enter key press
    self.process_selection(event.row_key)

Preserving Cursor Position

def refresh_table(self):
    table = self.query_one(DataTable)
    
    # Save position
    cursor_row = table.cursor_row
    selected_key = list(table.rows.keys())[cursor_row] if table.rows else None
    
    # Update data
    table.clear()
    # ... add new data ...
    
    # Restore position
    if selected_key and selected_key in table.rows:
        row_index = list(table.rows.keys()).index(selected_key)
        table.move_cursor(row=row_index, animate=False)

Styling

DataTable supports CSS styling but does NOT have:

  • set_row_style() method
  • set_cell_style() method

Use CSS classes and selectors instead:

DataTable > .datatable--cursor {
    background: $primary 30%;
}

DataTable > .datatable--header {
    text-style: bold;
}

Type Hints

from textual.widgets.data_table import RowKey, ColumnKey, CellKey
from textual.coordinate import Coordinate

# RowKey and ColumnKey are not strings - convert with str() if needed
row_key_str = str(row_key)

Common Errors and Solutions

  1. TypeError: 'RowKey' is not iterable

    • Solution: Convert to string first: str(row_key)
  2. AttributeError: 'DataTable' has no attribute 'set_row_style'

    • Solution: Use CSS styling instead
  3. Event not firing

    • Check handler name: on_data_table_row_highlighted not on_data_table_cursor_moved