Files
StreamLens/Documentation/textual/datatable.md

242 lines
5.7 KiB
Markdown
Raw Permalink Normal View History

# DataTable Widget API Reference
## Overview
The DataTable widget displays tabular data with support for selection, scrolling, and styling.
## Import
```python
from textual.widgets import DataTable
```
## Class Hierarchy
```
Widget → ScrollView → DataTable
```
## Constructor
```python
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
```python
# 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
```python
# 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
```python
# 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
```python
# 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
```python
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
```python
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
```python
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
```python
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
```python
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:
```css
DataTable > .datatable--cursor {
background: $primary 30%;
}
DataTable > .datatable--header {
text-style: bold;
}
```
## Type Hints
```python
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`