DataTables#

#

Data tables display sets of data across rows and columns.

https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-m3-previous.png

Note

MDDataTable allows developers to sort the data provided by column. This happens thanks to the use of an external function that you can bind while you’re defining the table columns. Be aware that the sorting function must return a 2 value list in the format of: [Index, Sorted_Row_Data]

This is because the index list is needed to allow MDDataTable to keep track of the selected rows. and, after the data is sorted, update the row checkboxes.

API - kivymd.uix.datatables.datatables#

class kivymd.uix.datatables.datatables.MDDataTable(**kwargs)#

Datatable class.

For more information, see in the ThemableBehavior and AnchorLayout classes documentation.

Events:
on_row_press

Called when a table row is clicked.

on_check_press

Called when the check box in the table row is checked.

Use events as follows

from kivy.metrics import dp

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable
from kivymd.uix.screen import MDScreen


class Example(MDApp):
    def build(self):
        self.data_tables = MDDataTable(
            use_pagination=True,
            check=True,
            column_data=[
                ("No.", dp(30)),
                ("Status", dp(30)),
                ("Signal Name", dp(60), self.sort_on_signal),
                ("Severity", dp(30)),
                ("Stage", dp(30)),
                ("Schedule", dp(30), self.sort_on_schedule),
                ("Team Lead", dp(30), self.sort_on_team),
            ],
            row_data=[
                (
                    "1",
                    ("alert", [255 / 256, 165 / 256, 0, 1], "No Signal"),
                    "Astrid: NE shared managed",
                    "Medium",
                    "Triaged",
                    "0:33",
                    "Chase Nguyen",
                ),
                (
                    "2",
                    ("alert-circle", [1, 0, 0, 1], "Offline"),
                    "Cosmo: prod shared ares",
                    "Huge",
                    "Triaged",
                    "0:39",
                    "Brie Furman",
                ),
                (
                    "3",
                    (
                        "checkbox-marked-circle",
                        [39 / 256, 174 / 256, 96 / 256, 1],
                        "Online",
                    ),
                    "Phoenix: prod shared lyra-lists",
                    "Minor",
                    "Not Triaged",
                    "3:12",
                    "Jeremy lake",
                ),
                (
                    "4",
                    (
                        "checkbox-marked-circle",
                        [39 / 256, 174 / 256, 96 / 256, 1],
                        "Online",
                    ),
                    "Sirius: NW prod shared locations",
                    "Negligible",
                    "Triaged",
                    "13:18",
                    "Angelica Howards",
                ),
                (
                    "5",
                    (
                        "checkbox-marked-circle",
                        [39 / 256, 174 / 256, 96 / 256, 1],
                        "Online",
                    ),
                    "Sirius: prod independent account",
                    "Negligible",
                    "Triaged",
                    "22:06",
                    "Diane Okuma",
                ),
            ],
            sorted_on="Schedule",
            sorted_order="ASC",
            elevation=2,
        )
        self.data_tables.bind(on_row_press=self.on_row_press)
        self.data_tables.bind(on_check_press=self.on_check_press)
        screen = MDScreen()
        screen.add_widget(self.data_tables)
        return screen

    def on_row_press(self, instance_table, instance_row):
        '''Called when a table row is clicked.'''

        print(instance_table, instance_row)

    def on_check_press(self, instance_table, current_row):
        '''Called when the check box in the table row is checked.'''

        print(instance_table, current_row)

    # Sorting Methods:
    # since the https://github.com/kivymd/KivyMD/pull/914 request, the
    # sorting method requires you to sort out the indexes of each data value
    # for the support of selections.
    #
    # The most common method to do this is with the use of the builtin function
    # zip and enumerate, see the example below for more info.
    #
    # The result given by these funcitons must be a list in the format of
    # [Indexes, Sorted_Row_Data]

    def sort_on_signal(self, data):
        return zip(*sorted(enumerate(data), key=lambda l: l[1][2]))

    def sort_on_schedule(self, data):
        return zip(
            *sorted(
                enumerate(data),
                key=lambda l: sum(
                    [
                        int(l[1][-2].split(":")[0]) * 60,
                        int(l[1][-2].split(":")[1]),
                    ]
                ),
            )
        )

    def sort_on_team(self, data):
        return zip(*sorted(enumerate(data), key=lambda l: l[1][-1]))


Example().run()
column_data#

Data for header columns.

from kivy.metrics import dp

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable
from kivy.uix.anchorlayout import AnchorLayout


class Example(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "Orange"

        layout = AnchorLayout()
        self.data_tables = MDDataTable(
            size_hint=(0.7, 0.6),
            use_pagination=True,
            check=True,
            # name column, width column, sorting function column(optional), custom tooltip
            column_data=[
                ("No.", dp(30), None, "Custom tooltip"),
                ("Status", dp(30)),
                ("Signal Name", dp(60)),
                ("Severity", dp(30)),
                ("Stage", dp(30)),
                ("Schedule", dp(30), lambda *args: print("Sorted using Schedule")),
                ("Team Lead", dp(30)),
            ],
        )
        layout.add_widget(self.data_tables)
        return layout


Example().run()
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-column-data.png

column_data is an ListProperty and defaults to [].

Note

The functions which will be called for sorting must accept a data argument and return the sorted data. Incoming data format will be similar to the provided row_data except that it’ll be all list instead of tuple like below. Any icon provided initially will also be there in this data so handle accordingly.

[
    [
        "1",
        ["icon", "No Signal"],
        "Astrid: NE shared managed",
        "Medium",
        "Triaged",
        "0:33",
        "Chase Nguyen",
    ],
    [
        "2",
        "Offline",
        "Cosmo: prod shared ares",
        "Huge",
        "Triaged",
        "0:39",
        "Brie Furman",
    ],
    [
        "3",
        "Online",
        "Phoenix: prod shared lyra-lists",
        "Minor",
        "Not Triaged",
        "3:12",
        "Jeremy lake",
    ],
    [
        "4",
        "Online",
        "Sirius: NW prod shared locations",
        "Negligible",
        "Triaged",
        "13:18",
        "Angelica Howards",
    ],
    [
        "5",
        "Online",
        "Sirius: prod independent account",
        "Negligible",
        "Triaged",
        "22:06",
        "Diane Okuma",
    ],
]

You must sort inner lists in ascending order and return the sorted data in the same format.

row_data#

Data for rows. To add icon in addition to a row data, include a tuple with This property stores the row data used to display each row in the DataTable To show an icon inside a column in a row, use the folowing format in the row’s columns.

Format:

(“MDicon-name”, [icon color in rgba], “Column Value”)

Example:

[...]
row_data = [

    # row 1
    [
        "value 1",
        "value 2",
        # the third value will have an icon inside the box
        ["home", [128/255, 48/255, 76/255, 1], "Offie" ]
    ],

    # row 2
    [
        "value 1",
        "value 2",
        # the third value will have an icon inside the box
        ["git", [1, 0.1, 0.1, 1], "Git Repo" ]
    ]
]

For a more complex example see below.

from kivy.metrics import dp
from kivy.uix.anchorlayout import AnchorLayout

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable


class Example(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "Orange"

        layout = AnchorLayout()
        data_tables = MDDataTable(
            size_hint=(0.9, 0.6),
            column_data=[
                ("Column 1", dp(30)),
                ("Column 2", dp(30)),
                ("Column 3", dp(50), self.sort_on_col_3),
                ("Column 4", dp(30)),
                ("Column 5", dp(30)),
                ("Column 6", dp(30)),
                ("Column 7", dp(30), self.sort_on_col_2),
            ],
            row_data=[
                # The number of elements must match the length
                # of the `column_data` list.
                (
                    "1",
                    ("alert", [255 / 256, 165 / 256, 0, 1], "No Signal"),
                    "Astrid: NE shared managed",
                    "Medium",
                    "Triaged",
                    "0:33",
                    "Chase Nguyen",
                ),
                (
                    "2",
                    ("alert-circle", [1, 0, 0, 1], "Offline"),
                    "Cosmo: prod shared ares",
                    "Huge",
                    "Triaged",
                    "0:39",
                    "Brie Furman",
                ),
                (
                    "3",
                    (
                        "checkbox-marked-circle",
                        [39 / 256, 174 / 256, 96 / 256, 1],
                        "Online",
                    ),
                    "Phoenix: prod shared lyra-lists",
                    "Minor",
                    "Not Triaged",
                    "3:12",
                    "Jeremy lake",
                ),
                (
                    "4",
                    (
                        "checkbox-marked-circle",
                        [39 / 256, 174 / 256, 96 / 256, 1],
                        "Online",
                    ),
                    "Sirius: NW prod shared locations",
                    "Negligible",
                    "Triaged",
                    "13:18",
                    "Angelica Howards",
                ),
                (
                    "5",
                    (
                        "checkbox-marked-circle",
                        [39 / 256, 174 / 256, 96 / 256, 1],
                        "Online",
                    ),
                    "Sirius: prod independent account",
                    "Negligible",
                    "Triaged",
                    "22:06",
                    "Diane Okuma",
                ),
            ],
        )
        layout.add_widget(data_tables)
        return layout

    def sort_on_col_3(self, data):
        return zip(
            *sorted(
                enumerate(data),
                key=lambda l: l[1][3]
            )
        )

    def sort_on_col_2(self, data):
        return zip(
            *sorted(
                enumerate(data),
                key=lambda l: l[1][-1]
            )
        )

Example().run()
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-row-data.png

Custom widgets in cells.

from kivy.metrics import dp
from kivy.uix.anchorlayout import AnchorLayout

from kivymd.app import MDApp
from kivymd.uix.button import MDButton, MDButtonText
from kivymd.uix.chip import MDChip, MDChipText
from kivymd.uix.datatables import MDDataTable


class MyMDChip(MDChip):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.widgets = [
            MDChipText(
                text="Chip"
            ),
        ]


class MyMDButton(MDButton):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.widgets = [
            MDButtonText(
                text="Button"
            )
        ]


class Example(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "Orange"

        layout = AnchorLayout()

        def on_activate(row_index: int, row_data: list) -> None:
            '''
            Callback function for the switch widget in the table row.

            Called when the MDSwitch in a table row is toggled.

            :param row_index: Index of the row in the table (0-based)
            :param row_data: List of data values for the row (all columns)

            Example:
                When a switch is toggled in the "Status" column:
                >>> on_activate(0, ['1', 'John Doe', {'viewclass': 'MDSwitch', ...}])
                Activate row 0: ['1', 'John Doe', {'viewclass': 'MDSwitch', ...}]
            '''

            print(f"Activate row {row_index}: {row_data}")

        def on_press(row_index: int, row_data: list) -> None:
            '''
            Callback function for button widgets in the table row.
            Called when a button (e.g., MyMDButton) in a table row is pressed/released.
            '''

            print(f"Press button {row_index}: {row_data}")

        def on_release(row_index: int, row_data: list) -> None:
            '''
            Callback function for check widgets in the table row.
            Called when a button (e.g., MyMDChip) in a table row is pressed/released.
            '''

            print(f"Press check {row_index}: {row_data}")

        data_tables = MDDataTable(
            size_hint=(0.95, 0.8),
            use_pagination=True,
            rows_num=5,
            check=True,
            column_data=[
                ("ID", dp(40)),
                ("Name", dp(40)),
                ("Status", dp(40)),
            ],
            row_data=[
                (
                    "1",
                    "John Doe",
                    {"viewclass": "MyMDButton", "on_press": on_press},
                ),
                (
                    "2",
                    "Jane Smith",
                    {"viewclass": "MDSwitch", "on_active": on_activate},
                ),
                (
                    "3",
                    "Nicol Andersson",
                    {"viewclass": "MyMDChip", "on_release": on_release},
                ),
            ]
        )

        layout.add_widget(data_tables)
        return layout


if __name__ == "__main__":
    Example().run()
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-custom-widgets.png

Custom widgets with children in cells.

from kivy.metrics import dp
from kivy.properties import StringProperty
from kivy.uix.anchorlayout import AnchorLayout

from kivymd.app import MDApp
from kivymd.uix.button import MDButton, MDButtonText
from kivymd.uix.chip import MDChip, MDChipText
from kivymd.uix.datatables import MDDataTable
from kivymd.uix.boxlayout import MDBoxLayout  # NOQA
from kivymd.uix.button import MDIconButton  # NOQA


class MyMDChip(MDChip):
    text = StringProperty()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def on_text(self, instance, value):
        self.widgets = [
            MDChipText(
                text=value
            ),
        ]


class MyMDButton(MDButton):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.widgets = [
            MDButtonText(
                text="Button"
            )
        ]


class Example(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "Orange"

        layout = AnchorLayout()

        def on_activate(row_index: int, row_data: list) -> None:
            print(f"Activate row {row_index}: {row_data}")

        def on_press(row_index: int, row_data: list) -> None:
            print(f"Press button {row_index}: {row_data}")

        def on_release(row_index: int, row_data: list) -> None:
            print(f"Release chip {row_index}: {row_data}")

        def on_edit(row_index: int, row_data: list) -> None:
            print(f"Edit row {row_index}: {row_data}")

        def on_delete(row_index: int, row_data: list) -> None:
            print(f"Delete row {row_index}: {row_data}")

        def on_view(row_index: int, row_data: list) -> None:
            print(f"View row {row_index}: {row_data}")

        data_tables = MDDataTable(
            size_hint=(0.95, 0.8),
            use_pagination=True,
            rows_num=5,
            check=True,
            column_data=[
                ("ID", dp(30)),
                ("Name", dp(40)),
                ("Status", dp(40)),
                ("Actions", dp(40)),
            ],
            row_data=[
                (
                    "1",
                    "John Doe",
                    {"viewclass": "MyMDButton", "on_press": on_press},
                    {
                        "viewclass": "MDBoxLayout",
                        "spacing": dp(4),
                        "children": [
                            {
                                "viewclass": "MDIconButton",
                                "icon": "eye",
                                "on_release": on_view,
                            },
                            {
                                "viewclass": "MDIconButton",
                                "icon": "pencil",
                                "on_release": on_edit,
                            },
                            {
                                "viewclass": "MDIconButton",
                                "icon": "delete",
                                "on_release": on_delete,
                            },
                        ]
                    },
                ),
                (
                    "2",
                    "Jane Smith",
                    {"viewclass": "MDSwitch", "on_active": on_activate},
                    {
                        "viewclass": "MDBoxLayout",
                        "spacing": dp(4),
                        "children": [
                            {
                                "viewclass": "MDIconButton",
                                "icon": "eye",
                                "on_release": on_view,
                            },
                            {
                                "viewclass": "MDIconButton",
                                "icon": "pencil",
                                "on_release": on_edit,
                            },
                            {
                                "viewclass": "MDIconButton",
                                "icon": "delete",
                                "on_release": on_delete,
                            },
                        ]
                    },
                ),
                (
                    "3",
                    "Nicol Andersson",
                    {"viewclass": "MyMDChip", "text": "Delete", "on_release": on_release},
                    {
                        "viewclass": "MDBoxLayout",
                        "spacing": dp(4),
                        "children": [
                            {
                                "viewclass": "MDIconButton",
                                "icon": "eye",
                                "on_release": on_view,
                            },
                            {
                                "viewclass": "MDIconButton",
                                "icon": "pencil",
                                "on_release": on_edit,
                            },
                            {
                                "viewclass": "MDIconButton",
                                "icon": "delete",
                                "on_release": on_delete,
                            },
                        ]
                    },
                ),
                (
                    "4",
                    "Alice Brown",
                    {
                        "viewclass": "MDBoxLayout",
                        "spacing": dp(4),
                        "children": [
                            {
                                "viewclass": "MyMDChip",
                                "text": "Active",
                            },
                            {
                                "viewclass": "MDIconButton",
                                "icon": "information",
                                "on_release": on_view,
                            },
                        ]
                    },
                    {
                        "viewclass": "MDBoxLayout",
                        "spacing": dp(4),
                        "children": [
                            {
                                "viewclass": "MDIconButton",
                                "icon": "pencil",
                                "on_release": on_edit,
                            },
                            {
                                "viewclass": "MDIconButton",
                                "icon": "delete",
                                "on_release": on_delete,
                            },
                        ]
                    },
                ),
                (
                    "5",
                    "Bob Johnson",
                    {
                        "viewclass": "MDBoxLayout",
                        "spacing": dp(4),
                        "children": [
                            {
                                "viewclass": "MyMDChip",
                                "text": "Pending",
                            },
                            {
                                "viewclass": "MDIconButton",
                                "icon": "information",
                                "on_release": on_view,
                            },
                        ]
                    },
                    {
                        "viewclass": "MDBoxLayout",
                        "spacing": dp(4),
                        "children": [
                            {
                                "viewclass": "MDIconButton",
                                "icon": "pencil",
                                "on_release": on_edit,
                            },
                            {
                                "viewclass": "MDIconButton",
                                "icon": "delete",
                                "on_release": on_delete,
                            },
                        ]
                    },
                ),
            ]
        )

        layout.add_widget(data_tables)
        return layout


if __name__ == "__main__":
    Example().run()
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-custom-widgets-children.png

row_data is an ListProperty and defaults to [].

sorted_on#

Column name upon which the data is already sorted.

If the table data is showing an already sorted data then this can be used to indicate upon which column the data is sorted.

sorted_on is an StringProperty and defaults to ‘’.

sorted_order#

Order of already sorted data. Must be one of ‘ASC’ for ascending or ‘DSC’ for descending order.

sorted_order is an OptionProperty and defaults to ‘ASC’.

check#

Use or not use checkboxes for rows.

https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-check.png

check is an BooleanProperty and defaults to False.

use_pagination#

Use page pagination for table or not.

from kivy.metrics import dp
from kivy.uix.anchorlayout import AnchorLayout

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable


class Example(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "Orange"

        layout = AnchorLayout()
        data_tables = MDDataTable(
            size_hint=(0.9, 0.6),
            use_pagination=True,
            column_data=[
                ("No.", dp(30)),
                ("Column 1", dp(30)),
                ("Column 2", dp(30)),
                ("Column 3", dp(30)),
                ("Column 4", dp(30)),
                ("Column 5", dp(30)),
            ],
            row_data=[
                (f"{i + 1}", "1", "2", "3", "4", "5") for i in range(50)
            ],
        )
        layout.add_widget(data_tables)
        return layout


Example().run()
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-use-pagination.png

use_pagination is an BooleanProperty and defaults to False.

radius#

See kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_radius attribute.

Added in version 1.2.0.

radius is an VariableListProperty and defaults to [dp(6), dp(6), dp(6), dp(6)].

rows_num#

The number of rows displayed on one page of the table.

https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-use-pagination-rows-num.png

rows_num is an NumericProperty and defaults to 10.

pagination_menu_pos#

Menu position for selecting the number of displayed rows. Available options are ‘center’, ‘auto’.

Center

https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-pos-top.png

Auto

https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-pos-auto.png

pagination_menu_pos is an OptionProperty and defaults to ‘center’.

pagination_menu_height#

Menu height for selecting the number of displayed rows.

240dp

https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-height-240.png

pagination_menu_height is an NumericProperty and defaults to ‘140dp’.

background_color#

Background color in the format (r, g, b, a) or string format. See background_color.

Use markup strings#

from kivy.metrics import dp
from kivy.uix.anchorlayout import AnchorLayout

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable


class Example(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "Orange"

        layout = AnchorLayout()
        data_tables = MDDataTable(
            size_hint=(0.9, 0.6),
            use_pagination=True,
            column_data=[
                ("No.", dp(30)),
                ("Column 1", dp(30)),
                ("[color=#52251B]Column 2[/color]", dp(30)),
                ("Column 3", dp(30)),
                ("[size=24][color=#C042B8]Column 4[/color][/size]", dp(30)),
                ("Column 5", dp(30)),
            ],
            row_data=[
                (
                    f"{i + 1}",
                    "[color=#297B50]1[/color]",
                    "[color=#C552A1]2[/color]",
                    "[color=#6C9331]3[/color]",
                    "4",
                    "5",
                )
                for i in range(50)
            ],
        )
        layout.add_widget(data_tables)
        return layout


Example().run()
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/datatables-use-markup-strings.png

background_color is a ColorProperty and defaults to None.

background_color_header#

Background color in the format (r, g, b, a) or string format for TableHeader class.

Added in version 1.0.0.

self.data_tables = MDDataTable(
    ...,
    background_color_header="#65275d",
)
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-background-color-header.png

background_color_header is a ColorProperty and defaults to None.

background_color_cell#

Background color in the format (r, g, b, a) or string format for CellRow class.

Added in version 1.0.0.

self.data_tables = MDDataTable(
    ...,
    background_color_header="#65275d",
    background_color_cell="#451938",
)
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-background-color-cell.png

background_color_cell is a ColorProperty and defaults to None.

background_color_selected_cell#

Background selected color in the format (r, g, b, a) or string format for CellRow class.

Added in version 1.0.0.

self.data_tables = MDDataTable(
    ...,
    background_color_header="#65275d",
    background_color_cell="#451938",
    background_color_selected_cell="e4514f",
)
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-background-color-selected-cell.png

background_color_selected_cell is a ColorProperty and defaults to None.

effect_cls#

Effect class. See kivy/effects package for more information.

Added in version 1.0.0.

effect_cls is an ObjectProperty and defaults to StiffScrollEffect.

set_row_checked(row_index: int, checked: bool) None#

Sets the checkbox state for a specific row by its index.

Added in version 2.0.0.

Parameters:
  • row_index – Row index in row_data

  • checked – True - check the row, False - uncheck the row

from kivy.metrics import dp
from kivy.lang import Builder
from kivy.properties import ObjectProperty

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable
from kivymd.uix.screen import MDScreen
from kivymd.uix.anchorlayout import MDAnchorLayout

KV = '''
<TableScreen>
    tablebox: tablebox
    md_bg_color: self.theme_cls.backgroundColor

    MainCard:
        pos_hint: {"center_x": .5, "center_y": .55}

        TableBox:
            id: tablebox

    MDButton:
        pos_hint: {"center_x": .5, "center_y": .1}
        on_press: root.check_row_0()

        MDButtonText:
            text: "Check row 0"


<TableBox>


<MainCard>
    size_hint: None, None
    size: "400dp", "450dp"
    pos_hint: {"center_x": .5, "center_y": .5}
    elevation: 3
    padding: "10dp"
    spacing: "25dp"
'''

Builder.load_string(KV)


class MainCard(MDScreen): ...


class TableBox(MDAnchorLayout):
    table: MDDataTable

    def add_table(
        self,
        column_fields,
        table_data,
        refresh=False,
        use_pagination=True,
        use_check=True,
        rows_num=10,
    ):
        if refresh:
            self.clear_widgets()

        data_table = MDDataTable(
            use_pagination=use_pagination,
            check=use_check,
            rows_num=rows_num,
            column_data=column_fields,
            row_data=table_data,
        )

        self.table = data_table
        self.add_widget(data_table)


class TableScreen(MDScreen):
    tablebox = ObjectProperty(None)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        col_fields = ["field1", "field2"]
        col_data = [(f, dp(30)) for f in col_fields]
        table_data = [(f"col1_{i}", f"col2_{i}") for i in range(30)]
        self.tablebox.add_table(col_data, table_data)

    def check_row_0(self):
        '''Select the checkbox for row 0.'''

        self.tablebox.table.set_row_checked(0, True)


class MainApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"
        return TableScreen()


if __name__ == "__main__":
    MainApp().run()
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/datatables-use-set_row_checked.gif

You can select multiple rows at once:

def check_row_0_4(self):
    '''Select the checkbox for row 0-4.'''

    self.tablebox.table.set_rows_checked([0, 1, 2, 3, 4], True)
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/datatables-use-set_row_checked-multiple.gif

Or toggle the selected row:

def toggle_row_5(self):
    '''Toggle the checkbox for row 5.'''

    self.tablebox.table.toggle_row_checked(5)
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/datatables-use-set_row_checke_toggle.gif
set_rows_checked(row_indices: list, checked: bool) None#

Sets the checkbox state for multiple rows.

Added in version 2.0.0.

Parameters:
  • row_indices – List of row indices in row_data

  • checked – True - check the rows, False - uncheck the rows

set_all_rows_checked(checked: bool) None#

Sets the state of all checkboxes in the table.

Parameters:

checked – True - check all rows, False - uncheck all rows

toggle_row_checked(row_index: int) None#

Toggles the checkbox state for a specific row.

Added in version 2.0.0.

Parameters:

row_index – Row index in row_data

is_row_checked(row_index: int) bool#

Checks if a specific row is checked.

Added in version 2.0.0.

Parameters:

row_index – Row index in row_data

Returns:

True if the row is checked, False otherwise

get_checked_row_indices() list#

Returns a list of indices of all checked rows.

Returns:

List of checked row indices

clear_all_checks() None#

Unchecks all rows in the table.

check_all_rows() None#

Checks all rows in the table.

update_row_data(instance_data_table, data: list) None#

Called when a the widget data must be updated.

Remember that this is a heavy function. since the whole data set must be updated. you can get better results calling this metod with in a coroutine.

add_row(data: list | tuple) None#

Added new row to common table. Argument data is the row data from the list row_data.

Add/remove row

from kivy.metrics import dp

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.button import MDButton
from kivymd.uix.button import MDButtonText


class Example(MDApp):
    data_tables = None

    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "Orange"

        layout = MDFloatLayout()  # root layout
        # Creating control buttons.
        button_box = MDBoxLayout(
            pos_hint={"center_x": 0.5},
            adaptive_size=True,
            padding="24dp",
            spacing="24dp",
        )

        for button_text in ["Add row", "Remove row"]:
            button_box.add_widget(
                MDButton(
                    MDButtonText(
                        text=button_text
                    ),
                    on_release=lambda x, y=button_text: self.on_button_press(y)
                )
            )

        # Create a table.
        self.data_tables = MDDataTable(
            pos_hint={"center_y": 0.5, "center_x": 0.5},
            size_hint=(0.9, 0.6),
            use_pagination=False,
            column_data=[
                ("No.", dp(30)),
                ("Column 1", dp(40)),
                ("Column 2", dp(40)),
                ("Column 3", dp(40)),
            ],
            row_data=[("1", "1", "2", "3")],
        )
        # Adding a table and buttons to the toot layout.
        layout.add_widget(self.data_tables)
        layout.add_widget(button_box)

        return layout

    def on_button_press(self, button_text: str) -> None:
        '''Called when a control button is clicked.'''

        try:
            {
                "Add row": self.add_row,
                "Remove row": self.remove_row,
            }[button_text]()
        except KeyError:
            pass

    def add_row(self) -> None:
        last_num_row = int(self.data_tables.row_data[-1][0])
        self.data_tables.add_row((str(last_num_row + 1), "1", "2", "3"))

    def remove_row(self) -> None:
        if len(self.data_tables.row_data) > 1:
            self.data_tables.remove_row(self.data_tables.row_data[-1])


Example().run()
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-add-remove-row.gif

Deleting checked rows#

from kivy.metrics import dp
from kivy.lang import Builder
from kivy.clock import Clock

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable
from kivymd.uix.screen import MDScreen

KV = '''
MDBoxLayout:
    orientation: "vertical"
    padding: "56dp"
    spacing: "24dp"

    MDData:
        id: table_screen

    MDButton:
        on_release: table_screen.delete_checked_rows()

        MDButtonText:
            text: "DELETE CHECKED ROWS"
'''


class MDData(MDScreen):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.data = [
            ["1", "Asep Sudrajat", "Male", "Soccer"],
            ["2", "Egy", "Male", "Soccer"],
            ["3", "Tanos", "Demon", "Soccer"],
        ]
        self.data_tables = MDDataTable(
            use_pagination=True,
            check=True,
            column_data=[
                ("No", dp(30)),
                ("No Urut.", dp(30)),
                ("Alamat Pengirim", dp(30)),
                ("No Surat", dp(60)),
            ]
        )
        self.data_tables.row_data = self.data
        self.add_widget(self.data_tables)

    def delete_checked_rows(self):
        def deselect_rows(*args):
            self.data_tables.table_data.select_all("normal")

        for data in self.data_tables.get_row_checks():
            self.data_tables.remove_row(data)

        Clock.schedule_once(deselect_rows)


class MyApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "Orange"
        return Builder.load_string(KV)


MyApp().run()
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-deleting-checked-rows.gif

Added in version 1.0.0.

remove_row(data: list | tuple) None#

Removed row from common table. Argument data is the row data from the list row_data.

See the code in the doc string for the add_row method for more information.

Added in version 1.0.0.

update_row(old_data: list | tuple, new_data: list | tuple) None#

Updates a table row. Argument old_data/new_data is the row data from the list row_data.

Update row

from kivy.metrics import dp

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.button import MDButton, MDButtonText


class Example(MDApp):
    data_tables = None

    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "Orange"

        layout = MDFloatLayout()
        layout.add_widget(
            MDButton(
                MDButtonText(
                    text="Change 2 row"
                ),
                pos_hint={"center_x": 0.5},
                on_release=self.update_row,
                y=24,
            )
        )
        self.data_tables = MDDataTable(
            pos_hint={"center_y": 0.5, "center_x": 0.5},
            size_hint=(0.9, 0.6),
            use_pagination=False,
            column_data=[
                ("No.", dp(30)),
                ("Column 1", dp(40)),
                ("Column 2", dp(40)),
                ("Column 3", dp(40)),
            ],
            row_data=[(f"{i + 1}", "1", "2", "3") for i in range(3)],
        )
        layout.add_widget(self.data_tables)

        return layout

    def update_row(self, instance_button: MDButton) -> None:
        self.data_tables.update_row(
            self.data_tables.row_data[1],  # old row data
            ["2", "A", "B", "C"],  # new row data
        )


Example().run()
https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-change-row.gif

Added in version 1.0.0.

on_row_press(instance_cell_row) None#

Called when a table row is clicked.

on_check_press(row_data: list) None#

Called when the check box in the table row is checked.

Parameters:

row_data – One of the elements from the MDDataTable.row_data list.

get_row_checks() list#

Returns all rows that are checked.

create_pagination_menu(interval: int | float) None#