Skip to content

DataTable

A table widget optimized for displaying a lot of data.

  • Focusable
  • Container

Guide

Adding data

The following example shows how to fill a table with data. First, we use add_columns to include the lane, swimmer, country, and time columns in the table. After that, we use the add_rows method to insert the rows into the table.

TableApp  lane  swimmer               country        time    4     Joseph Schooling      Singapore      50.39   2     Michael Phelps        United States  51.14   5     Chad le Clos          South Africa   51.14   6     László Cseh           Hungary        51.14   3     Li Zhuhao             China          51.26   8     Mehdy Metella         France         51.58   7     Tom Shields           United States  51.73   1     Aleksandr Sadovnikov  Russia         51.84   10    Darren Burns          Scotland       51.84 

from textual.app import App, ComposeResult
from textual.widgets import DataTable

ROWS = [
    ("lane", "swimmer", "country", "time"),
    (4, "Joseph Schooling", "Singapore", 50.39),
    (2, "Michael Phelps", "United States", 51.14),
    (5, "Chad le Clos", "South Africa", 51.14),
    (6, "László Cseh", "Hungary", 51.14),
    (3, "Li Zhuhao", "China", 51.26),
    (8, "Mehdy Metella", "France", 51.58),
    (7, "Tom Shields", "United States", 51.73),
    (1, "Aleksandr Sadovnikov", "Russia", 51.84),
    (10, "Darren Burns", "Scotland", 51.84),
]


class TableApp(App):
    def compose(self) -> ComposeResult:
        yield DataTable()

    def on_mount(self) -> None:
        table = self.query_one(DataTable)
        table.add_columns(*ROWS[0])
        table.add_rows(ROWS[1:])


app = TableApp()
if __name__ == "__main__":
    app.run()

To add a single row or column use add_row and add_column, respectively.

Styling and justifying cells

Cells can contain more than just plain strings - Rich renderables such as Text are also supported. Text objects provide an easy way to style and justify cell content:

TableApp  lane  swimmer               country        time      4    Joseph Schooling    Singapore50.39    2      Michael PhelpsUnited States51.14    5        Chad le Clos South Africa51.14    6         László Cseh      Hungary51.14    3           Li Zhuhao        China51.26    8       Mehdy Metella       France51.58    7         Tom ShieldsUnited States51.73    1Aleksandr Sadovnikov       Russia51.84   10        Darren Burns     Scotland51.84

from rich.text import Text

from textual.app import App, ComposeResult
from textual.widgets import DataTable

ROWS = [
    ("lane", "swimmer", "country", "time"),
    (4, "Joseph Schooling", "Singapore", 50.39),
    (2, "Michael Phelps", "United States", 51.14),
    (5, "Chad le Clos", "South Africa", 51.14),
    (6, "László Cseh", "Hungary", 51.14),
    (3, "Li Zhuhao", "China", 51.26),
    (8, "Mehdy Metella", "France", 51.58),
    (7, "Tom Shields", "United States", 51.73),
    (1, "Aleksandr Sadovnikov", "Russia", 51.84),
    (10, "Darren Burns", "Scotland", 51.84),
]


class TableApp(App):
    def compose(self) -> ComposeResult:
        yield DataTable()

    def on_mount(self) -> None:
        table = self.query_one(DataTable)
        table.add_columns(*ROWS[0])
        for row in ROWS[1:]:
            # Adding styled and justified `Text` objects instead of plain strings.
            styled_row = [
                Text(str(cell), style="italic #03AC13", justify="right") for cell in row
            ]
            table.add_row(*styled_row)


app = TableApp()
if __name__ == "__main__":
    app.run()

Keys

When adding a row to the table, you can supply a key to add_row. A key is a unique identifier for that row. If you don't supply a key, Textual will generate one for you and return it from add_row. This key can later be used to reference the row, regardless of its current position in the table.

When working with data from a database, for example, you may wish to set the row key to the primary key of the data to ensure uniqueness. The method add_column also accepts a key argument and works similarly.

Keys are important because cells in a data table can change location due to factors like row deletion and sorting. Thus, using keys instead of coordinates allows us to refer to data without worrying about its current location in the table.

If you want to change the table based solely on coordinates, you can use the coordinate_to_cell_key method to convert a coordinate to a cell key, which is a (row_key, column_key) pair.

Cursors

The coordinate of the cursor is exposed via the cursor_coordinate reactive attribute. Three types of cursors are supported: cell, row, and column. Change the cursor type by assigning to the cursor_type reactive attribute.

TableApp  lane  swimmer               country        time    4     Joseph Schooling      Singapore      50.39   2     Michael Phelps        United States  51.14   5     Chad le Clos          South Africa   51.14   6     László Cseh           Hungary        51.14   3     Li Zhuhao             China          51.26   8     Mehdy Metella         France         51.58   7     Tom Shields           United States  51.73   1     Aleksandr Sadovnikov  Russia         51.84   10    Darren Burns          Scotland       51.84 

TableApp  lane  swimmer               country        time    4     Joseph Schooling      Singapore      50.39   2     Michael Phelps        United States  51.14   5     Chad le Clos          South Africa   51.14   6     László Cseh           Hungary        51.14   3     Li Zhuhao             China          51.26   8     Mehdy Metella         France         51.58   7     Tom Shields           United States  51.73   1     Aleksandr Sadovnikov  Russia         51.84   10    Darren Burns          Scotland       51.84 

TableApp  lane  swimmer               country        time    4     Joseph Schooling      Singapore      50.39   2     Michael Phelps        United States  51.14   5     Chad le Clos          South Africa   51.14   6     László Cseh           Hungary        51.14   3     Li Zhuhao             China          51.26   8     Mehdy Metella         France         51.58   7     Tom Shields           United States  51.73   1     Aleksandr Sadovnikov  Russia         51.84   10    Darren Burns          Scotland       51.84 

from itertools import cycle

from textual.app import App, ComposeResult
from textual.widgets import DataTable

ROWS = [
    ("lane", "swimmer", "country", "time"),
    (4, "Joseph Schooling", "Singapore", 50.39),
    (2, "Michael Phelps", "United States", 51.14),
    (5, "Chad le Clos", "South Africa", 51.14),
    (6, "László Cseh", "Hungary", 51.14),
    (3, "Li Zhuhao", "China", 51.26),
    (8, "Mehdy Metella", "France", 51.58),
    (7, "Tom Shields", "United States", 51.73),
    (1, "Aleksandr Sadovnikov", "Russia", 51.84),
    (10, "Darren Burns", "Scotland", 51.84),
]

cursors = cycle(["column", "row", "cell"])


class TableApp(App):
    def compose(self) -> ComposeResult:
        yield DataTable()

    def on_mount(self) -> None:
        table = self.query_one(DataTable)
        table.cursor_type = next(cursors)
        table.zebra_stripes = True
        table.add_columns(*ROWS[0])
        table.add_rows(ROWS[1:])

    def key_c(self):
        table = self.query_one(DataTable)
        table.cursor_type = next(cursors)


app = TableApp()
if __name__ == "__main__":
    app.run()

You can change the position of the cursor using the arrow keys, Page Up, Page Down, Home and End, or by assigning to the cursor_coordinate reactive attribute.

Updating data

Cells can be updated in the DataTable by using the update_cell and update_cell_at methods.

Removing data

To remove all data in the table, use the clear method. To remove individual rows, use remove_row. The remove_row method accepts a key argument, which identifies the row to be removed.

If you wish to remove the row below the cursor in the DataTable, use coordinate_to_cell_key to get the row key of the row under the current cursor_coordinate, then supply this key to remove_row:

# Get the keys for the row and column under the cursor.
row_key, _ = table.coordinate_to_cell_key(table.cursor_coordinate)
# Supply the row key to `remove_row` to delete the row.
table.remove_row(row_key)

Removing columns

To remove individual columns, use remove_column. The remove_column method accepts a key argument, which identifies the column to be removed.

You can remove the column below the cursor using the same coordinate_to_cell_key method described above:

# Get the keys for the row and column under the cursor.
_, column_key = table.coordinate_to_cell_key(table.cursor_coordinate)
# Supply the column key to `column_row` to delete the column.
table.remove_column(column_key)

Fixed data

You can fix a number of rows and columns in place, keeping them pinned to the top and left of the table respectively. To do this, assign an integer to the fixed_rows or fixed_columns reactive attributes of the DataTable.

TableApp  A   B    C     1   2    3     2   4    6     79  158  237   80  160  240   81  162  243   82  164  246   83  166  249   84  168  252   85  170  255   86  172  258   87  174  261   88  176  264   89  178  267   90  180  270   91  182  273   92  184  276   93  186  279   94  188  282 ▇▇  95  190  285   96  192  288   97  194  291   98  196  294   99  198  297 

from textual.app import App, ComposeResult
from textual.widgets import DataTable


class TableApp(App):
    CSS = "DataTable {height: 1fr}"

    def compose(self) -> ComposeResult:
        yield DataTable()

    def on_mount(self) -> None:
        table = self.query_one(DataTable)
        table.focus()
        table.add_columns("A", "B", "C")
        for number in range(1, 100):
            table.add_row(str(number), str(number * 2), str(number * 3))
        table.fixed_rows = 2
        table.fixed_columns = 1
        table.cursor_type = "row"
        table.zebra_stripes = True


app = TableApp()
if __name__ == "__main__":
    app.run()

In the example above, we set fixed_rows to 2, and fixed_columns to 1, meaning the first two rows and the leftmost column do not scroll - they always remain visible as you scroll through the data table.

Sorting

The DataTable can be sorted using the sort method. In order to sort your data by a column, you must have supplied a key to the add_column method when you added it. You can then pass this key to the sort method to sort by that column. Additionally, you can sort by multiple columns by passing multiple keys to sort.

Labelled rows

A "label" can be attached to a row using the add_row method. This will add an extra column to the left of the table which the cursor cannot interact with. This column is similar to the leftmost column in a spreadsheet containing the row numbers. The example below shows how to attach simple numbered labels to rows.

TableApp  lane  swimmer               country        time   1 4     Joseph Schooling      Singapore      50.39  2 2     Michael Phelps        United States  51.14  3 5     Chad le Clos          South Africa   51.14  4 6     László Cseh           Hungary        51.14  5 3     Li Zhuhao             China          51.26  6 8     Mehdy Metella         France         51.58  7 7     Tom Shields           United States  51.73  8 1     Aleksandr Sadovnikov  Russia         51.84  9 10    Darren Burns          Scotland       51.84 

from rich.text import Text

from textual.app import App, ComposeResult
from textual.widgets import DataTable

ROWS = [
    ("lane", "swimmer", "country", "time"),
    (4, "Joseph Schooling", "Singapore", 50.39),
    (2, "Michael Phelps", "United States", 51.14),
    (5, "Chad le Clos", "South Africa", 51.14),
    (6, "László Cseh", "Hungary", 51.14),
    (3, "Li Zhuhao", "China", 51.26),
    (8, "Mehdy Metella", "France", 51.58),
    (7, "Tom Shields", "United States", 51.73),
    (1, "Aleksandr Sadovnikov", "Russia", 51.84),
    (10, "Darren Burns", "Scotland", 51.84),
]


class TableApp(App):
    def compose(self) -> ComposeResult:
        yield DataTable()

    def on_mount(self) -> None:
        table = self.query_one(DataTable)
        table.add_columns(*ROWS[0])
        for number, row in enumerate(ROWS[1:], start=1):
            label = Text(str(number), style="#B0FC38 italic")
            table.add_row(*row, label=label)


app = TableApp()
if __name__ == "__main__":
    app.run()

Reactive Attributes

Name Type Default Description
show_header bool True Show the table header
show_row_labels bool True Show the row labels (if applicable)
fixed_rows int 0 Number of fixed rows (rows which do not scroll)
fixed_columns int 0 Number of fixed columns (columns which do not scroll)
zebra_stripes bool False Display alternating colors on rows
header_height int 1 Height of header row
show_cursor bool True Show the cursor
cursor_type str "cell" One of "cell", "row", "column", or "none"
cursor_coordinate Coordinate Coordinate(0, 0) The current coordinate of the cursor
hover_coordinate Coordinate Coordinate(0, 0) The coordinate the mouse cursor is above

Messages

Bindings

The data table widget defines the following bindings:

Key(s) Description
enter Select cells under the cursor.
up Move the cursor up.
down Move the cursor down.
right Move the cursor right.
left Move the cursor left.

Component Classes

The data table widget provides the following component classes:

Class Description
datatable--cursor Target the cursor.
datatable--hover Target the cells under the hover cursor.
datatable--fixed Target fixed columns and fixed rows.
datatable--fixed-cursor Target highlighted and fixed columns or header.
datatable--header Target the header of the data table.
datatable--header-cursor Target cells highlighted by the cursor.
datatable--header-hover Target hovered header or row label cells.
datatable--even-row Target even rows (row indices start at 0).
datatable--odd-row Target odd rows (row indices start at 0).

textual.widgets.DataTable class

def __init__(
    self,
    *,
    show_header=True,
    show_row_labels=True,
    fixed_rows=0,
    fixed_columns=0,
    zebra_stripes=False,
    header_height=1,
    show_cursor=True,
    cursor_foreground_priority="css",
    cursor_background_priority="renderable",
    cursor_type="cell",
    name=None,
    id=None,
    classes=None,
    disabled=False
):

Bases: ScrollView, Generic[CellType]

A tabular widget that contains data.

BINDINGS class-attribute

BINDINGS: list[BindingType] = [
    Binding("enter", "select_cursor", "Select", show=False),
    Binding("up", "cursor_up", "Cursor Up", show=False),
    Binding(
        "down", "cursor_down", "Cursor Down", show=False
    ),
    Binding(
        "right", "cursor_right", "Cursor Right", show=False
    ),
    Binding(
        "left", "cursor_left", "Cursor Left", show=False
    ),
    Binding("pageup", "page_up", "Page Up", show=False),
    Binding(
        "pagedown", "page_down", "Page Down", show=False
    ),
]
Key(s) Description
enter Select cells under the cursor.
up Move the cursor up.
down Move the cursor down.
right Move the cursor right.
left Move the cursor left.

COMPONENT_CLASSES class-attribute

COMPONENT_CLASSES: set[str] = {
    "datatable--cursor",
    "datatable--hover",
    "datatable--fixed",
    "datatable--fixed-cursor",
    "datatable--header",
    "datatable--header-cursor",
    "datatable--header-hover",
    "datatable--odd-row",
    "datatable--even-row",
}
Class Description
datatable--cursor Target the cursor.
datatable--hover Target the cells under the hover cursor.
datatable--fixed Target fixed columns and fixed rows.
datatable--fixed-cursor Target highlighted and fixed columns or header.
datatable--header Target the header of the data table.
datatable--header-cursor Target cells highlighted by the cursor.
datatable--header-hover Target hovered header or row label cells.
datatable--even-row Target even rows (row indices start at 0).
datatable--odd-row Target odd rows (row indices start at 0).

columns instance-attribute

columns: dict[ColumnKey, Column] = {}

Metadata about the columns of the table, indexed by their key.

cursor_background_priority instance-attribute

cursor_background_priority = cursor_background_priority

Should we prioritize the cursor component class CSS background or the renderable background in the event where a cell contains a renderable with a background color.

cursor_column property

cursor_column: int

The index of the column that the DataTable cursor is currently on.

cursor_coordinate class-attribute instance-attribute

cursor_coordinate: Reactive[Coordinate] = Reactive(
    Coordinate(0, 0), repaint=False, always_update=True
)

Current cursor Coordinate.

This can be set programmatically or changed via the method move_cursor.

cursor_foreground_priority instance-attribute

cursor_foreground_priority = cursor_foreground_priority

Should we prioritize the cursor component class CSS foreground or the renderable foreground in the event where a cell contains a renderable with a foreground color.

cursor_row property

cursor_row: int

The index of the row that the DataTable cursor is currently on.

cursor_type class-attribute instance-attribute

cursor_type: Reactive[CursorType] = cursor_type

The type of cursor of the DataTable.

fixed_columns class-attribute instance-attribute

fixed_columns = fixed_columns

The number of columns to fix (prevented from scrolling).

fixed_rows class-attribute instance-attribute

fixed_rows = fixed_rows

The number of rows to fix (prevented from scrolling).

header_height class-attribute instance-attribute

header_height = header_height

The height of the header row (the row of column labels).

hover_column property

hover_column: int

The index of the column that the mouse cursor is currently hovering above.

hover_coordinate class-attribute instance-attribute

hover_coordinate: Reactive[Coordinate] = Reactive(
    Coordinate(0, 0), repaint=False, always_update=True
)

The coordinate of the DataTable that is being hovered.

hover_row property

hover_row: int

The index of the row that the mouse cursor is currently hovering above.

ordered_columns property

ordered_columns: list[Column]

The list of Columns in the DataTable, ordered as they appear on screen.

ordered_rows property

ordered_rows: list[Row]

The list of Rows in the DataTable, ordered as they appear on screen.

row_count property

row_count: int

The number of rows currently present in the DataTable.

rows instance-attribute

rows: dict[RowKey, Row] = {}

Metadata about the rows of the table, indexed by their key.

show_cursor class-attribute instance-attribute

show_cursor = show_cursor

Show/hide both the keyboard and hover cursor.

show_header class-attribute instance-attribute

show_header = show_header

Show/hide the header row (the row of column labels).

show_row_labels class-attribute instance-attribute

show_row_labels = show_row_labels

Show/hide the column containing the labels of rows.

zebra_stripes class-attribute instance-attribute

zebra_stripes = zebra_stripes

Apply zebra effect on row backgrounds (light, dark, light, dark, ...).

CellHighlighted class

def __init__(self, data_table, value, coordinate, cell_key):

Bases: Message

Posted when the cursor moves to highlight a new cell.

This is only relevant when the cursor_type is "cell". It's also posted when the cell cursor is re-enabled (by setting show_cursor=True), and when the cursor type is changed to "cell". Can be handled using on_data_table_cell_highlighted in a subclass of DataTable or in a parent widget in the DOM.

cell_key instance-attribute

cell_key: CellKey = cell_key

The key for the highlighted cell.

control property

control: DataTable

Alias for the data table.

coordinate instance-attribute

coordinate: Coordinate = coordinate

The coordinate of the highlighted cell.

data_table instance-attribute

data_table = data_table

The data table.

value instance-attribute

value: CellType = value

The value in the highlighted cell.

CellSelected class

def __init__(self, data_table, value, coordinate, cell_key):

Bases: Message

Posted by the DataTable widget when a cell is selected.

This is only relevant when the cursor_type is "cell". Can be handled using on_data_table_cell_selected in a subclass of DataTable or in a parent widget in the DOM.

cell_key instance-attribute

cell_key: CellKey = cell_key

The key for the selected cell.

control property

control: DataTable

Alias for the data table.

coordinate instance-attribute

coordinate: Coordinate = coordinate

The coordinate of the cell that was selected.

data_table instance-attribute

data_table = data_table

The data table.

value instance-attribute

value: CellType = value

The value in the cell that was selected.

ColumnHighlighted class

def __init__(self, data_table, cursor_column, column_key):

Bases: Message

Posted when a column is highlighted.

This message is only posted when the cursor_type is set to "column". Can be handled using on_data_table_column_highlighted in a subclass of DataTable or in a parent widget in the DOM.

column_key instance-attribute

column_key = column_key

The key of the column that was highlighted.

control property

control: DataTable

Alias for the data table.

cursor_column instance-attribute

cursor_column: int = cursor_column

The x-coordinate of the column that was highlighted.

data_table instance-attribute

data_table = data_table

The data table.

ColumnSelected class

def __init__(self, data_table, cursor_column, column_key):

Bases: Message

Posted when a column is selected.

This message is only posted when the cursor_type is set to "column". Can be handled using on_data_table_column_selected in a subclass of DataTable or in a parent widget in the DOM.

column_key instance-attribute

column_key = column_key

The key of the column that was selected.

control property

control: DataTable

Alias for the data table.

cursor_column instance-attribute

cursor_column: int = cursor_column

The x-coordinate of the column that was selected.

data_table instance-attribute

data_table = data_table

The data table.

HeaderSelected class

def __init__(self, data_table, column_key, column_index, label):

Bases: Message

Posted when a column header/label is clicked.

column_index instance-attribute

column_index = column_index

The index for the column.

column_key instance-attribute

column_key = column_key

The key for the column.

control property

control: DataTable

Alias for the data table.

data_table instance-attribute

data_table = data_table

The data table.

label instance-attribute

label = label

The text of the label.

RowHighlighted class

def __init__(self, data_table, cursor_row, row_key):

Bases: Message

Posted when a row is highlighted.

This message is only posted when the cursor_type is set to "row". Can be handled using on_data_table_row_highlighted in a subclass of DataTable or in a parent widget in the DOM.

control property

control: DataTable

Alias for the data table.

cursor_row instance-attribute

cursor_row: int = cursor_row

The y-coordinate of the cursor that highlighted the row.

data_table instance-attribute

data_table = data_table

The data table.

row_key instance-attribute

row_key: RowKey = row_key

The key of the row that was highlighted.

RowLabelSelected class

def __init__(self, data_table, row_key, row_index, label):

Bases: Message

Posted when a row label is clicked.

control property

control: DataTable

Alias for the data table.

data_table instance-attribute

data_table = data_table

The data table.

label instance-attribute

label = label

The text of the label.

row_index instance-attribute

row_index = row_index

The index for the column.

row_key instance-attribute

row_key = row_key

The key for the column.

RowSelected class

def __init__(self, data_table, cursor_row, row_key):

Bases: Message

Posted when a row is selected.

This message is only posted when the cursor_type is set to "row". Can be handled using on_data_table_row_selected in a subclass of DataTable or in a parent widget in the DOM.

control property

control: DataTable

Alias for the data table.

cursor_row instance-attribute

cursor_row: int = cursor_row

The y-coordinate of the cursor that made the selection.

data_table instance-attribute

data_table = data_table

The data table.

row_key instance-attribute

row_key: RowKey = row_key

The key of the row that was selected.

action_page_down method

def action_page_down(self):

Move the cursor one page down.

action_page_up method

def action_page_up(self):

Move the cursor one page up.

action_scroll_end method

def action_scroll_end(self):

Scroll to the bottom of the data table.

action_scroll_home method

def action_scroll_home(self):

Scroll to the top of the data table.

add_column method

def add_column(
    self, label, *, width=None, key=None, default=None
):

Add a column to the table.

Parameters
Name Type Description Default
label TextType

A str or Text object containing the label (shown top of column).

required
width int | None

Width of the column in cells or None to fit content.

None
key str | None

A key which uniquely identifies this column. If None, it will be generated for you.

None
default CellType | None

The value to insert into pre-existing rows.

None
Returns
Type Description
ColumnKey

Uniquely identifies this column. Can be used to retrieve this column regardless of its current location in the DataTable (it could have moved after being added due to sorting/insertion/deletion of other columns).

add_columns method

def add_columns(self, *labels):

Add a number of columns.

Parameters
Name Type Description Default
*labels TextType

Column headers.

()
Returns
Type Description
list[ColumnKey]

A list of the keys for the columns that were added. See the add_column method docstring for more information on how these keys are used.

add_row method

def add_row(self, *cells, height=1, key=None, label=None):

Add a row at the bottom of the DataTable.

Parameters
Name Type Description Default
*cells CellType

Positional arguments should contain cell data.

()
height int | None

The height of a row (in lines). Use None to auto-detect the optimal height.

1
key str | None

A key which uniquely identifies this row. If None, it will be generated for you and returned.

None
label TextType | None

The label for the row. Will be displayed to the left if supplied.

None
Returns
Type Description
RowKey

Unique identifier for this row. Can be used to retrieve this row regardless of its current location in the DataTable (it could have moved after being added due to sorting or insertion/deletion of other rows).

add_rows method

def add_rows(self, rows):

Add a number of rows at the bottom of the DataTable.

Parameters
Name Type Description Default
rows Iterable[Iterable[CellType]]

Iterable of rows. A row is an iterable of cells.

required
Returns
Type Description
list[RowKey]

A list of the keys for the rows that were added. See the add_row method docstring for more information on how these keys are used.

clear method

def clear(self, columns=False):

Clear the table.

Parameters
Name Type Description Default
columns bool

Also clear the columns.

False
Returns
Type Description
Self

The DataTable instance.

coordinate_to_cell_key method

def coordinate_to_cell_key(self, coordinate):

Return the key for the cell currently occupying this coordinate.

Parameters
Name Type Description Default
coordinate Coordinate

The coordinate to exam the current cell key of.

required
Returns
Type Description
CellKey

The key of the cell currently occupying this coordinate.

Raises
Type Description
CellDoesNotExist

If the coordinate is not valid.

get_cell method

def get_cell(self, row_key, column_key):

Given a row key and column key, return the value of the corresponding cell.

Parameters
Name Type Description Default
row_key RowKey | str

The row key of the cell.

required
column_key ColumnKey | str

The column key of the cell.

required
Returns
Type Description
CellType

The value of the cell identified by the row and column keys.

get_cell_at method

def get_cell_at(self, coordinate):

Get the value from the cell occupying the given coordinate.

Parameters
Name Type Description Default
coordinate Coordinate

The coordinate to retrieve the value from.

required
Returns
Type Description
CellType

The value of the cell at the coordinate.

Raises
Type Description
CellDoesNotExist

If there is no cell with the given coordinate.

get_cell_coordinate method

def get_cell_coordinate(self, row_key, column_key):

Given a row key and column key, return the corresponding cell coordinate.

Parameters
Name Type Description Default
row_key RowKey | str

The row key of the cell.

required
column_key Column | str

The column key of the cell.

required
Returns
Type Description
Coordinate

The current coordinate of the cell identified by the row and column keys.

Raises
Type Description
CellDoesNotExist

If the specified cell does not exist.

get_column method

def get_column(self, column_key):

Get the values from the column identified by the given column key.

Parameters
Name Type Description Default
column_key ColumnKey | str

The key of the column.

required
Returns
Type Description
Iterable[CellType]

A generator which yields the cells in the column.

Raises
Type Description
ColumnDoesNotExist

If there is no column corresponding to the key.

get_column_at method

def get_column_at(self, column_index):

Get the values from the column at a given index.

Parameters
Name Type Description Default
column_index int

The index of the column.

required
Returns
Type Description
Iterable[CellType]

A generator which yields the cells in the column.

Raises
Type Description
ColumnDoesNotExist

If there is no column with the given index.

get_column_index method

def get_column_index(self, column_key):

Return the current index for the column identified by column_key.

Parameters
Name Type Description Default
column_key ColumnKey | str

The column key to find the current index of.

required
Returns
Type Description
int

The current index of the specified column key.

Raises
Type Description
ColumnDoesNotExist

If the column key does not exist.

get_row method

def get_row(self, row_key):

Get the values from the row identified by the given row key.

Parameters
Name Type Description Default
row_key RowKey | str

The key of the row.

required
Returns
Type Description
list[CellType]

A list of the values contained within the row.

Raises
Type Description
RowDoesNotExist

When there is no row corresponding to the key.

get_row_at method

def get_row_at(self, row_index):

Get the values from the cells in a row at a given index. This will return the values from a row based on the rows current position in the table.

Parameters
Name Type Description Default
row_index int

The index of the row.

required
Returns
Type Description
list[CellType]

A list of the values contained in the row.

Raises
Type Description
RowDoesNotExist

If there is no row with the given index.

get_row_height method

def get_row_height(self, row_key):

Given a row key, return the height of that row in terminal cells.

Parameters
Name Type Description Default
row_key RowKey

The key of the row.

required
Returns
Type Description
int

The height of the row, measured in terminal character cells.

get_row_index method

def get_row_index(self, row_key):

Return the current index for the row identified by row_key.

Parameters
Name Type Description Default
row_key RowKey | str

The row key to find the current index of.

required
Returns
Type Description
int

The current index of the specified row key.

Raises
Type Description
RowDoesNotExist

If the row key does not exist.

is_valid_column_index method

def is_valid_column_index(self, column_index):

Return a boolean indicating whether the column_index is within table bounds.

Parameters
Name Type Description Default
column_index int

The column index to check.

required
Returns
Type Description
bool

True if the column index is within the bounds of the table.

is_valid_coordinate method

def is_valid_coordinate(self, coordinate):

Return a boolean indicating whether the given coordinate is valid.

Parameters
Name Type Description Default
coordinate Coordinate

The coordinate to validate.

required
Returns
Type Description
bool

True if the coordinate is within the bounds of the table.

is_valid_row_index method

def is_valid_row_index(self, row_index):

Return a boolean indicating whether the row_index is within table bounds.

Parameters
Name Type Description Default
row_index int

The row index to check.

required
Returns
Type Description
bool

True if the row index is within the bounds of the table.

move_cursor method

def move_cursor(self, *, row=None, column=None, animate=False):

Move the cursor to the given position.

Example
datatable = app.query_one(DataTable)
datatable.move_cursor(row=4, column=6)
# datatable.cursor_coordinate == Coordinate(4, 6)
datatable.move_cursor(row=3)
# datatable.cursor_coordinate == Coordinate(3, 6)
Parameters
Name Type Description Default
row int | None

The new row to move the cursor to.

None
column int | None

The new column to move the cursor to.

None
animate bool

Whether to animate the change of coordinates.

False

refresh_column method

def refresh_column(self, column_index):

Refresh the column at the given index.

Parameters
Name Type Description Default
column_index int

The index of the column to refresh.

required
Returns
Type Description
Self

The DataTable instance.

refresh_coordinate method

def refresh_coordinate(self, coordinate):

Refresh the cell at a coordinate.

Parameters
Name Type Description Default
coordinate Coordinate

The coordinate to refresh.

required
Returns
Type Description
Self

The DataTable instance.

refresh_row method

def refresh_row(self, row_index):

Refresh the row at the given index.

Parameters
Name Type Description Default
row_index int

The index of the row to refresh.

required
Returns
Type Description
Self

The DataTable instance.

remove_column method

def remove_column(self, column_key):

Remove a column (identified by a key) from the DataTable.

Parameters
Name Type Description Default
column_key ColumnKey | str

The key identifying the column to remove.

required
Raises
Type Description
ColumnDoesNotExist

If the column key does not exist.

remove_row method

def remove_row(self, row_key):

Remove a row (identified by a key) from the DataTable.

Parameters
Name Type Description Default
row_key RowKey | str

The key identifying the row to remove.

required
Raises
Type Description
RowDoesNotExist

If the row key does not exist.

sort method

def sort(self, *columns, reverse=False):

Sort the rows in the DataTable by one or more column keys.

Parameters
Name Type Description Default
columns ColumnKey | str

One or more columns to sort by the values in.

()
reverse bool

If True, the sort order will be reversed.

False
Returns
Type Description
Self

The DataTable instance.

update_cell method

def update_cell(
    self, row_key, column_key, value, *, update_width=False
):

Update the cell identified by the specified row key and column key.

Parameters
Name Type Description Default
row_key RowKey | str

The key identifying the row.

required
column_key ColumnKey | str

The key identifying the column.

required
value CellType

The new value to put inside the cell.

required
update_width bool

Whether to resize the column width to accommodate for the new cell content.

False
Raises
Type Description
CellDoesNotExist

When the supplied row_key and column_key cannot be found in the table.

update_cell_at method

def update_cell_at(
    self, coordinate, value, *, update_width=False
):

Update the content inside the cell currently occupying the given coordinate.

Parameters
Name Type Description Default
coordinate Coordinate

The coordinate to update the cell at.

required
value CellType

The new value to place inside the cell.

required
update_width bool

Whether to resize the column width to accommodate for the new cell content.

False

textual.widgets.data_table

CursorType module-attribute

CursorType = Literal['cell', 'row', 'column', 'none']

The valid types of cursors for DataTable.cursor_type.

CellDoesNotExist class

Bases: Exception

The cell key/index was invalid.

Raised when the coordinates or cell key provided does not exist in the DataTable (e.g. out of bounds index, invalid key)

CellKey class

Bases: NamedTuple

A unique identifier for a cell in the DataTable.

Even if the cell changes visual location (i.e. moves to a different coordinate in the table), this key can still be used to retrieve it, regardless of where it currently is.

Column class

Metadata for a column in the DataTable.

render_width property

render_width: int

Width in cells, required to render a column.

ColumnDoesNotExist class

Bases: Exception

Raised when the column index or column key provided does not exist in the DataTable (e.g. out of bounds index, invalid key)

ColumnKey class

Bases: StringKey

Uniquely identifies a column in the DataTable.

Even if the visual location of the column changes due to sorting or other modifications, a key will always refer to the same column.

DuplicateKey class

Bases: Exception

The key supplied already exists.

Raised when the RowKey or ColumnKey provided already refers to an existing row or column in the DataTable. Keys must be unique.

Row class

Metadata for a row in the DataTable.

RowDoesNotExist class

Bases: Exception

Raised when the row index or row key provided does not exist in the DataTable (e.g. out of bounds index, invalid key)

RowKey class

Bases: StringKey

Uniquely identifies a row in the DataTable.

Even if the visual location of the row changes due to sorting or other modifications, a key will always refer to the same row.